對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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容