对AWS Cognito的一些理解

AWS Cognito包含User Pool和Identity Pool两个产品。基于User Pool可以快速实现一套用户系统。Identity Pool用于实现联合身份认证。User Pool跟Identity Pool的关系如下面几张图所示。

image.png
image.png
image.png

通过AWS labs的demo可以体验Cognito的主要功能,github地址:https://github.com/awslabs/aws-sdk-ios-samples。

User Pool

aws-sdk-ios-samples里面CognitoYourUserPools-SampleCognitoAuth-Sample两个demo跟User Pool里面有关。要把这两个demo跑起来,要先在User Pool里面添加一个pool,接着添加一个App,再接着修改项目里面对应的配置。

image.png

CognitoYourUserPools-Sample支持注册、登录、找回密码等功能。

image.png

还有更简单的使用方式,那就是User Pool会提供一个OIDC server。

https://wla.auth.ap-southeast-2.amazoncognito.com/login?
response_type=code
&client_id=1t80si9ch1voi0bdusm5c9svn
&state=00a4715e-13b3-4da3-8553-dcc757d1d544
&redirect_uri=wla://signin
&scope=openid
&code_challenge=CHdOC4yZEQWOg3jZNCTm8b8v8jPnKjizRipIF0ltvr8
&code_challenge_method=S256

在控制台可以配置icon、前景色和背景色。之后点击Sign in按钮,会在In-App browser里面打开下面这个页面,挺好看的。

image.png
image.png

看起来这是一个标准的OIDC服务器,可以看看它的Discovery,然后就会发现其实也不是那么标准,里面有authorization_endpoint,并没有看到token_endpoint。看demo里面的玩法就更野了,根本不来请求这个Discovery,而是要使用Info.plist里面的AWS的配置去拼这些endpoint。

image.png

上面两个demo中都可以注册账号,可以在控制台里面看到这些账号。

image.png

为了满足用户多样的需求,User Pool在很多环节都可以设置Lambda function,非常有用。

image.png

Identity Pool

CognitoSync-Sample这个demo是展示Identity Pool功能的,这个demo就有点太粗糙了,居然也没有加入User Pool登录。

image.png

我配置了一下Facebook登录,登录了一下试试,感觉还挺溜。

image.png
image.png

token

User Pool登录成功得到的信息如下所示。看起来是OAuth那一套,这个AccessToken很长,是一个JWT Bearer Token,跟IdToken信息有重叠。这两个token都可以拿到https://jwt.io里面解开看看。具体的描述请参看:Using Tokens with User Pools。

{
    "AuthenticationResult": {
       "AccessToken": "eyJraWQiOiJicVQ4ZkViVzJCbXN2blZwcGRlUWQ0REhKaTZjdzNNZGhaTzJrN2s3c2w0PSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI4NzI2ZmFjZi1jNjNmLTRlNDQtOGM1YS1jOTE5YjdjNTMxMDYiLCJkZXZpY2Vfa2V5IjoiYXAtc291dGhlYXN0LTJfZjY1MjY0NjktNjBhMi00ZWUyLTk5MTMtNzAyYmE3NTllMjdjIiwidG9rZW5fdXNlIjoiYWNjZXNzIiwic2NvcGUiOiJhd3MuY29nbml0by5zaWduaW4udXNlci5hZG1pbiIsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl9IbkdrZVh5YUIiLCJleHAiOjE0OTgyMzU4MjEsImlhdCI6MTQ5ODIzMjIyMSwianRpIjoiNjcyMmUyM2EtMmQ4Mi00YTg2LWE1NWYtZjRjNjRjYjZmMTQ2IiwiY2xpZW50X2lkIjoiMXQ4MHNpOWNoMXZvaTBiZHVzbTVjOXN2biIsInVzZXJuYW1lIjoiaHMwMDIifQ.ONnjTQr0Qd2AaKCxfnBKT3TnMu-k8Jf_awBapH2A3QpzSIBBBYo3lQzL20JMP92gFfwho9XQGsUjPwNMfkIl19YZG_8BZSME1Aw6l9LT5Q35pGBiuaq1A82rOGmmfgS35RYQ25YxeF18_vO6e4gYdxvAHMSrK8zIJQvFWV6wQYkRpucphKg7bCrmdW5mJt_QyC64JA3JYuHGW2bkFM7IsTt9eop5igIxQTp7uR8oWsSLeYAsJ2nkAdRkbvVt1XvqNmFCU8iOIF0rtkm6bKGdYQprlxAHvyxFVTVBJt-42UWWGII7YaYQTF8k7Lhzu6HAlU27KzlSZ2279CVGKw2BVQ",
        "ExpiresIn": 3600,
        "IdToken": "eyJraWQiOiJlaFNtY1pjM1JBdEhGYkVWVFpucFBDNWZTSFwvSW15dUN1cmRHUk0wcUVrST0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI4NzI2ZmFjZi1jNjNmLTRlNDQtOGM1YS1jOTE5YjdjNTMxMDYiLCJhdWQiOiIxdDgwc2k5Y2gxdm9pMGJkdXNtNWM5c3ZuIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTQ5ODIzMjIyMSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmFwLXNvdXRoZWFzdC0yLmFtYXpvbmF3cy5jb21cL2FwLXNvdXRoZWFzdC0yX0huR2tlWHlhQiIsInBob25lX251bWJlcl92ZXJpZmllZCI6dHJ1ZSwiY29nbml0bzp1c2VybmFtZSI6ImhzMDAyIiwicGhvbmVfbnVtYmVyIjoiKzg2MTg5MDU4MTgyOTIiLCJleHAiOjE0OTgyMzU4MjEsImlhdCI6MTQ5ODIzMjIyMSwiZW1haWwiOiJjcWZ6am5lQGdtYWlsLmNvbSJ9.eV9osb4FQUAzCf4bDFGH9SHwuelC1v78oenxINihVGZ7aqJ82sozfSPtMMcsjN9sm32RZajoyBkw9Buni_bywwjv5FtVgoLb3aXkSvHxtNrXyT1Ligym2c3NJvsEC2aiVr5DFBIEZieSwdsLajcM5JSk9KYgO5OAiTuIe_TiKom2lfm7-n_uF0b09Z3GuYqHXkvufxJnXzb3gqxeY1_M6g3BqEu3Nta-kGqabzn_-6JsYgDY14jyBwRrydMqUqjfZjjLRgZxHBitWMWz0dp4wrTpHOGktqtVdjhj9m8-p4IXp-za3ADcoBh5QSCX49loHi2Mm45gfFiyEVLC3X4P7Q",
        "RefreshToken": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.VFeqGiKV-fH8uTpoihvbyS7FVcdPGiSQVZzf9CWL6UfD3ucm5RaL_J0Sm6kh_0T86gZJQdO1nZ2BBongemyipzSvrowOTUqnqk5sE-5mTU6VXZYzRevhnm-Gr2sF7o0Dx4IrI8Esjn2K0KMZx2TLGHGAHRvFTG5kmFJNR_80o9VRMXaN1X_1LEuJF58amfj1lMqUq0lWoLmWBb5AaCnfap3DuIBxq_egFTgV-JvhlZaHD9Y6L8RANh6Rv2YunCYdyMs8Dw8H7HZHSm5hSdB1sIh-e1M6PMVX-i0V_3R6_IkU0qnC_0NTQw_MvZFO6psjDKCNejAAbvMDoJO6zJsDVQ._B25kR6-WKz3zzJW.-5Xv72tm6qz-gnm2Ojf5QfSxGqFsvl_DlSqgHbYLaUJJLcjKlQGH1uhSohaivadFKT29cdoRH-rHATCSQuzia1RyiMXfYtF2a2DLv3gErS6Rgd4EyZWvddLTjWi0-QdrXvEp5Ry1P_2jakp7_Ng4vKRuvkm9kDHTeeLdLEwDIBJXNGXvIx7qHLBDaBbcP2O9ayU0vVSM3WdzkaHe2-hCEvaHe5w9ygLrzqEdpxv1MsP1botJcBPiBFIPCt-29EKMLoDNC9PU8jczJuGwqcGINuYt9S9kh6JMLw-rpX6wofX4h_B6uy8zEiN6JhQWIv4incFvJBjK1z5v8N51gcT3U1yzNtkeImiU8R-SWPl2gTp3SxguK_-FxhjBuQOHv8v1n_NMYkKz7PchFv77TVBEVDFmNg0cdB2gMhV2yk8x_HbNK5ttOncpN_sLDR1YML3YwIRjiWAz4cyCM6oAGOkSEFwkFcwqHy8PtLdXH2rxxhopUfGJAAUJdpxWC_NpoJFvrBT20794sUMEBRU9BBudsTargWSDZaycgYJN-VxYmFIfoqkejJt9iFs8XGZpx0Uz8qMxNic7g-Kl2CMtht5dgK-_DTlqity6d3CQe3kVjabmoVEwfniopEo_y_Uv7tICgAMc2ScOjg-YjFO3oKzdeOejlEmXV0EvivtICR-QChlqN-XlvWebwdruX6xkyYVh6Js12cH-V40Ll8PEaBVpIOlDe5hz53feR3X9hKmfbAqSZVp0Uk9fh_MJf7vh3XnHyamnTTpn4f-0q9lzHwbt6iiN4vxhCoePVwzLCl4FZFllO0XwVJJmhjCc9YbsIgV6BANjLjyHo5pmb8FfjrP95m5vJVHjRztNeYkr6njCL1rkNwxeAjXahPLKGyyyuIqEPfejWHIJJ7-HUfuof3SOwDVjXRK4j7rHpCMAVGUCWzffPtN4rFPqGNUHFMtXW2J05ydCXBXdHgA4WdbfYkrwSbSY51wLU_PW9RUubbAf0P9MS680TdyjZNfavy6l9LiMFfkwXAbVb0lFBbFzMzHRKotBdoJcr01RT2Kz8JOlihsFRDqXb-V0Z06Tku63uO23z9Usyxp3am8tnYhlBBrYe0L_cdRgEXqtSBipKchwfojsQh-uPzbzLX95XSMlLdedcSJSicaeT2VZqt8l-nJzXcGWQ9nFZxdzlT_XA-44hS-o8u1OrIvw_OlFyBd1KFAC5KBCu4SskkQWqg9iAH3Rn33mVGJqf8hcuSVKTYQ3YFyD8yvTmZOHYFnPW7Yc7Ecrg0-s4yXL._4s3xxrYlVU-0LPaIB6Auw",
        "TokenType": "Bearer"
    },
    "ChallengeParameters": {}
}

解开IdToken之后,看看里面的iatexp,可以发现IdToken的过期时间是一个小时。

image.png
image.png

Identity Pool登录成功之后得到的信息如下所示。看起来就是STS token啊。

{
    "Credentials": {
        "AccessKeyId": "ASIAI46U752A4IDXV2TA",
        "Expiration": 1498235294,
        "SecretKey": "rj6Kd07s1lbTpRNOXBNdzxxCY56G2jRN26yddHcW",
        "SessionToken": "AgoGb3JpZ2luEIP//////////wEaDmFwLXNvdXRoZWFzdC0yIoACNsPwXYx/zmX42sN3HEEHw/cY0yzELJdHTsF+C+HpUnbklUOmxTvgWIQ8/rVnUGWewsSrazIA5idbm4Chb2OAaPDKlGuAfq/ovZZS2HIhMWFBPnWzFggOsDlqe73QVhw96RW8t8dACTuoNEZjAlXPIPk90oZXHRctEiPr/vrzJYWy5M39RxgY3lxKAe3cosbIJhSARxIxuaudueYdC96xxQXSjQMn7sA5VGsjnU9hytgni4sDR0ozFUlfKi7OhuylKTiB5zIWaMmDnyt+SKfoC506RNPH/QNu3PLLqSUgVG6yMov0Eydub6T66lZgkDDYTmwmgKjze0Pd9aVw0qrapyrdBAjZ//////////8BEAAaDDk3ODM0MzM3MDU3NyIMMF7ptJyDwDX5/6gSKrEE3beePMNROAKR1bB54f+xnvo8ZUryymf430PkKHC3Q0oW1+eeBi44F1raX/Bv4tlq6WWK3RlrFl+gPNLeZC/b9xcyJI2q4luMBwYAbqXHKYJxwzlIhXHGjqxf27/01X9ksK3X8nove2y51TK84MHzxQjm4ABQfE2873mSS1YIbTgOBV7jDYn91pal4lXIrUilQIw1GUQ5m+SSHKfbpzwZpWTbnYesrXfWRd59pYaQ6yntat1/La/mZG5i/Dbk+HUOieyAGffMt5OICB75JpUkRjyMo8qNkdc4/nsEvMNTLl1LQdhVL6zmkKdztNZBbn76Uz1cr7u1sOJLCqHKY5P2uNuGvA11YaJN9MGLJwI+VNSGiDD7hT8Sor2bMHd3r9hy+SGAUfyhjPtch5D8tHwYTT/1GyBLyN2ws7ym/dYxHJ+4gpjK78J7VCjdR1BN5amtQTgzrZ9kjS7SkhVPVLxNJK3+GTk6M5asitd1V/BRwpBHtS1LCFqYAGdlOADVl+TKgo15OmATY9aKmwUoYQpZKV9cvk2ferOGCQwfv92F5QSqxGibb0+8/rJF4CIfpneXp2YLRu07FubicyhLa+pWuMJ5IwC2b6pbZho212PIjuuBrlH+TDEKNF6aC7f4RRnk87A/Chsgq32KxUZVgt5MtOr3LPrMmU1hB28yqb0ofabMq14o3vAgY3+SPa5NBWxQxhO/YN+vB9Y4J+I+p0dxb7amWQNzJLuCURUoK8RT0qfbMI7ntMoF"
    },
    "IdentityId": "ap-southeast-2:65d024cf-f342-4c5d-8ece-7d1736d24633"
}

IAM

User Pool和Identity Pool怎么跟AWS IAM关联起来呢?那就是配置role。User Pool可以创建group,然后把用户加入到group里面,而group可以设置role。详细的描述请看文档:Assigning IAM Roles to Groups。

image.png

Identity Pool同样可以创建和指定角色。

image.png

这些角色在AWS IAM里面都可以找到。但是User Pool和Identity Pool自己并不会出现在IAM的用户和组里面。

image.png

我有一个疑问是,如果一个账号在User Pool里面的角色是A,然而Identity Pool使用角色是B,那么我在Identity Pool里面登录了这个账号,那么他对应的角色是A还是B呢?还是拥有两个角色所属权限的交集或并集?

最后的总结

User Pool貌似是配合AWS API Gateway一起使用的。毕竟OAuth/OIDC这套东西非常成熟和标准,适用于HTTP协议下。

A user pool is integrated with an API as a method authorizer that 
is applicable for any method. When calling the methods with such 
an authorizer enabled, an API client includes in the request 
headers the user's identity token provisioned from the user pool. 
API Gateway then validates the token to ensure it belongs to the 
configured user pool and authenticates the caller before passing 
the request to the backend.

To integrate an API with the Amazon Cognito identity provider, 
you, as an API developer, create and own a user pool, create an 
API Gateway authorizer connected to the user pool, and enable 
the authorizer on selected API methods. You must also distribute 
to your API client developers the user pool ID, a client ID, and 
possibly the associated client secret that are provisioned from the 
user pool. The client will need this information to register users 
with the user pool, to provide the sign-in functionality, and to have 
the user's identity token provisioned from the user pool.
image.png

接着去AWS API Gateway里面看看。我发现在Authorizers里面可以指定使用Cognito User Pool Authorizer

image.png

Identity Pool给的就是STS token,所以可以直接拿去访问AWS Service。

Amazon Cognito Federated Identities enable you to create unique 
identities for your users and federate them with identity providers. 
With an identity, you can obtain temporary, limited-privilege AWS 
credentials to synchronize data with Amazon Cognito Sync, or 
directly access other AWS services. 

使用API Gateway

User Pool的id token可以用来调用API Gateway的API。API Gateway可以设置custom authorizer,这是一个User Pool。如果一个id token对应的用户属于这个User Pool,那么拿着id token就可以访问API。AWS也支持通过Identity Pool的方式来调用API Gateway,这样做会麻烦一些,需要使用API Gateway生成的接口SDK,配合相应的IAM role,才能调用成功。

  • 首先在API Gateway复制PetStore这个API。

  • Authorizers里面创建一个Cognito User Pool Authorizer,选择好region和User Pool。

image.png
  • 设置好之后,可以验证一下id token。id token可以从CognitoYourUserPools-Sampledemo的日志里面获取。如果id token这个用户不属于wla-demo这个User Pool,那么验证会失败。
image.png
  • pets的GET接口设置Authorization,选择上面创建好的custom authorizer。
image.png
  • 发布接口之后。在Postman里面做测试。HTTP Header里面设置Authorization为id token即可。如果只是设置一下HTTP Header,通过curl也可以做到,哈哈,用Postman牛刀杀鸡了。
image.png
  • 如果不设置Authorization,那么会提示如下错误。
image.png

对于整个流程下面几张图也有比较好的阐述。

image.png
image.png
image.png
image.png

最后简单总结一下吧。我觉得User Pool是一个完整的用户系统,实现了OAuth 2.0,并且支持SAML做SSO。User Pool可以跟API Gateway联动起来,方便用户做一个完整的Serverless应用。而Identity Pool则支持主流的ID Provider,包括User Pool,用户认证之后颁发STS token,用于访问AWS自己的服务。在AWS服务的归类中,Cognito属于移动服务这个类目下面。Cognito+API Gateway+Lambda function=Serverless,有这一套体系,加上AWS移动相关的SDK和服务,写一个App是一件非常惬意的事情。

image.png

参考资料

  1. Cognito User Pool vs Identity Pool
  2. Getting Started With Your User Pools In Amazon Cognito Slideshare
  3. Getting Started With Your User Pools In Amazon Cognito Youtube
  4. Securing Serverless Workloads with Cognito and API Gateway Part I
  5. Securing Serverless Workloads with Cognito and API Gateway Part II

你可能感兴趣的:(对AWS Cognito的一些理解)