開發人員驗證的身分 - Amazon Cognito

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

開發人員驗證的身分

除了透過 將 Facebook 設定為身分集區 IdP將 Google 設定為身分集區 IdP將 Amazon 登入設定為身分集區 IdP設定使用 Apple 登入作為身分集區 IdP 的 Web 聯合身分,Amazon Cognito 還支援開發人員驗證的身分。使用開發人員驗證身分,您可以透過自己的現有身分驗證程序註冊和驗證使用者,同時仍使用 Amazon Cognito 同步使用者資料和存取 AWS 資源。使用開發人員驗證的身分時,需要最終使用者裝置、身分驗證後端與 Amazon Cognito 之間的互動。如需詳細資訊,請參閱 AWS 部落格中的了解 Amazon Cognito 身分驗證第 2 部分:開發人員驗證身分

了解身分驗證流程

GetOpenIdTokenForDeveloperIdentity API 操作可以啟動增強型和基本身分驗證的開發人員身分驗證。此 API 會使用管理登入資料來驗證請求。Logins 映射是身分集區開發人員提供者名稱,如同與自訂識別符login.mydevprovider配對。

範例:

"Logins": { "login.mydevprovider": "my developer identifier" }

增強型身分驗證

呼叫 GetCredentialsForIdentity API 操作,並使用來自 的字符名稱cognito-identity.amazonaws.com和值的Logins映射GetOpenIdTokenForDeveloperIdentity

範例:

"Logins": { "cognito-identity.amazonaws.com": "eyJra12345EXAMPLE" }

GetCredentialsForIdentity 使用開發人員驗證身分,會傳回身分集區之預設驗證角色的臨時憑證。

基本身分驗證

呼叫 AssumeRoleWithWebIdentity API 操作,並請求任何已定義適當信任關係RoleArn之 IAM 角色的 。將 的值WebIdentityToken設定為從 取得的字符GetOpenIdTokenForDeveloperIdentity

如需開發人員驗證身分驗證流程以及其與外部提供者身分的差異資訊,請參閱 身分集區身分驗證流程

定義開發供應商名稱,並將其與身分集區建立關聯

若要使用開發人員驗證的身分,您需要有與開發供應商相關聯的身分池。若要執行此作業,請遵循下列步驟:

若要新增自訂開發供應商
  1. Amazon Cognito 主控台選擇 身分池。選取身分池。

  2. 選擇 使用者存取權 索引標籤。

  3. 選取 新增身分供應商

  4. 選擇 自訂開發人員提供者

  5. 輸入 開發人員供應商名稱。新增開發供應商之後,您無法變更或刪除。

  6. 選取儲存變更

備註:一旦設定供應商名稱,就無法再變更。

實作身分提供者

Android

若要使用開發人員驗證的身分,請實作您自己的身分供應商類別,擴展 AWSAbstractCognitoIdentityProvider。您的身分供應商類別應傳回包含字符做為屬性的回應物件。

下列是基礎身分提供者範例。

public class DeveloperAuthenticationProvider extends AWSAbstractCognitoDeveloperIdentityProvider { private static final String developerProvider = "<Developer_provider_name>"; public DeveloperAuthenticationProvider(String accountId, String identityPoolId, Regions region) { super(accountId, identityPoolId, region); // Initialize any other objects needed here. } // Return the developer provider name which you choose while setting up the // identity pool in the &COG; Console @Override public String getProviderName() { return developerProvider; } // Use the refresh method to communicate with your backend to get an // identityId and token. @Override public String refresh() { // Override the existing token setToken(null); // Get the identityId and token by making a call to your backend // (Call to your backend) // Call the update method with updated identityId and token to make sure // these are ready to be used from Credentials Provider. update(identityId, token); return token; } // If the app has a valid identityId return it, otherwise get a valid // identityId from your backend. @Override public String getIdentityId() { // Load the identityId from the cache identityId = cachedIdentityId; if (identityId == null) { // Call to your backend } else { return identityId; } } }

若要使用此身分提供者,您必須將其傳入 CognitoCachingCredentialsProvider。範例如下:

DeveloperAuthenticationProvider developerProvider = new DeveloperAuthenticationProvider( null, "IDENTITYPOOLID", context, Regions.USEAST1); CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider( context, developerProvider, Regions.USEAST1);

iOS - Objective-C

若要使用開發人員驗證的身分,請實作您自己的身分供應商類別,此類別會延伸 AWSCognitoCredentialsProviderHelper。您的身分提供者類別應傳回包含權杖做為屬性的回應物件。

@implementation DeveloperAuthenticatedIdentityProvider /* * Use the token method to communicate with your backend to get an * identityId and token. */ - (AWSTask <NSString*> *) token { //Write code to call your backend: //Pass username/password to backend or some sort of token to authenticate user //If successful, from backend call getOpenIdTokenForDeveloperIdentity with logins map //containing "your.provider.name":"enduser.username" //Return the identity id and token to client //You can use AWSTaskCompletionSource to do this asynchronously // Set the identity id and return the token self.identityId = response.identityId; return [AWSTask taskWithResult:response.token]; } @end

若要使用此身分提供者,請將其傳入 AWSCognitoCredentialsProvider,如下列範例所示。

DeveloperAuthenticatedIdentityProvider * devAuth = [[DeveloperAuthenticatedIdentityProvider alloc] initWithRegionType:AWSRegionYOUR_IDENTITY_POOL_REGION identityPoolId:@"YOUR_IDENTITY_POOL_ID" useEnhancedFlow:YES identityProviderManager:nil]; AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionYOUR_IDENTITY_POOL_REGION identityProvider:devAuth];

如果您想要同時支援未驗證的身分和開發人員驗證的身分,請覆寫 logins 實作中的 AWSCognitoCredentialsProviderHelper 方法。

- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins { if(/*logic to determine if user is unauthenticated*/) { return [AWSTask taskWithResult:nil]; }else{ return [super logins]; } }

如果您想要支援開發人員驗證的身分和社交供應商,您必須在 loginsAWSCognitoCredentialsProviderHelper 實作中,管理誰是目前的供應商。

- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins { if(/*logic to determine if user is unauthenticated*/) { return [AWSTask taskWithResult:nil]; }else if (/*logic to determine if user is Facebook*/){ return [AWSTask taskWithResult: @{ AWSIdentityProviderFacebook : [FBSDKAccessToken currentAccessToken] }]; }else { return [super logins]; } }

iOS - Swift

若要使用開發人員驗證的身分,請實作您自己的身分供應商類別,此類別會延伸 AWSCognitoCredentialsProviderHelper。您的身分提供者類別應傳回包含權杖做為屬性的回應物件。

import AWSCore /* * Use the token method to communicate with your backend to get an * identityId and token. */ class DeveloperAuthenticatedIdentityProvider : AWSCognitoCredentialsProviderHelper { override func token() -> AWSTask<NSString> { //Write code to call your backend: //pass username/password to backend or some sort of token to authenticate user, if successful, //from backend call getOpenIdTokenForDeveloperIdentity with logins map containing "your.provider.name":"enduser.username" //return the identity id and token to client //You can use AWSTaskCompletionSource to do this asynchronously // Set the identity id and return the token self.identityId = resultFromAbove.identityId return AWSTask(result: resultFromAbove.token) }

若要使用此身分提供者,請將其傳入 AWSCognitoCredentialsProvider,如下列範例所示。

let devAuth = DeveloperAuthenticatedIdentityProvider(regionType: .YOUR_IDENTITY_POOL_REGION, identityPoolId: "YOUR_IDENTITY_POOL_ID", useEnhancedFlow: true, identityProviderManager:nil) let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .YOUR_IDENTITY_POOL_REGION, identityProvider:devAuth) let configuration = AWSServiceConfiguration(region: .YOUR_IDENTITY_POOL_REGION, credentialsProvider:credentialsProvider) AWSServiceManager.default().defaultServiceConfiguration = configuration

如果您想要同時支援未驗證的身分和開發人員驗證的身分,請覆寫 logins 實作中的 AWSCognitoCredentialsProviderHelper 方法。

override func logins () -> AWSTask<NSDictionary> { if(/*logic to determine if user is unauthenticated*/) { return AWSTask(result:nil) }else { return super.logins() } }

如果您想要支援開發人員驗證的身分和社交供應商,您必須在 loginsAWSCognitoCredentialsProviderHelper 實作中,管理誰是目前的供應商。

override func logins () -> AWSTask<NSDictionary> { if(/*logic to determine if user is unauthenticated*/) { return AWSTask(result:nil) }else if (/*logic to determine if user is Facebook*/){ if let token = AccessToken.current?.authenticationToken { return AWSTask(result: [AWSIdentityProviderFacebook:token]) } return AWSTask(error:NSError(domain: "Facebook Login", code: -1 , userInfo: ["Facebook" : "No current Facebook access token"])) }else { return super.logins() } }

JavaScript

從後端取得身分 ID 和工作階段字符後,您必須將其傳遞至 AWS.CognitoIdentityCredentials 供應商中。範例如下。

AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'IDENTITY_POOL_ID', IdentityId: 'IDENTITY_ID_RETURNED_FROM_YOUR_PROVIDER', Logins: { 'cognito-identity.amazonaws.com': 'TOKEN_RETURNED_FROM_YOUR_PROVIDER' } });

Unity

若要使用開發人員驗證的身分,您必須擴展 CognitoAWSCredentials,並覆寫 RefreshIdentity 方法,以從後端擷取使用者身分 ID 和字符,並將其傳回。下列是身分供應商聯絡假設後端 'example.com' 的簡單範例:

using UnityEngine; using System.Collections; using Amazon.CognitoIdentity; using System.Collections.Generic; using ThirdParty.Json.LitJson; using System; using System.Threading; public class DeveloperAuthenticatedCredentials : CognitoAWSCredentials { const string PROVIDER_NAME = "example.com"; const string IDENTITY_POOL = "IDENTITY_POOL_ID"; static readonly RegionEndpoint REGION = RegionEndpoint.USEast1; private string login = null; public DeveloperAuthenticatedCredentials(string loginAlias) : base(IDENTITY_POOL, REGION) { login = loginAlias; } protected override IdentityState RefreshIdentity() { IdentityState state = null; ManualResetEvent waitLock = new ManualResetEvent(false); MainThreadDispatcher.ExecuteCoroutineOnMainThread(ContactProvider((s) => { state = s; waitLock.Set(); })); waitLock.WaitOne(); return state; } IEnumerator ContactProvider(Action<IdentityState> callback) { WWW www = new WWW("http://example.com/?username="+login); yield return www; string response = www.text; JsonData json = JsonMapper.ToObject(response); //The backend has to send us back an Identity and a OpenID token string identityId = json["IdentityId"].ToString(); string token = json["Token"].ToString(); IdentityState state = new IdentityState(identityId, PROVIDER_NAME, token, false); callback(state); } }

上述程式碼使用執行緒發送器物件來呼叫 coroutine。如果無法在您的專案中這麼做,您可以在您的場景中使用下列指令碼:

using System; using UnityEngine; using System.Collections; using System.Collections.Generic; public class MainThreadDispatcher : MonoBehaviour { static Queue<IEnumerator> _coroutineQueue = new Queue<IEnumerator>(); static object _lock = new object(); public void Update() { while (_coroutineQueue.Count > 0) { StartCoroutine(_coroutineQueue.Dequeue()); } } public static void ExecuteCoroutineOnMainThread(IEnumerator coroutine) { lock (_lock) { _coroutineQueue.Enqueue(coroutine); } } }

Xamarin

若要使用開發人員驗證的身分,您必須擴展 CognitoAWSCredentials,並覆寫 RefreshIdentity 方法,以從後端擷取使用者身分 ID 和字符,並將其傳回。下列是身分供應商聯絡假設後端 'example.com' 的基礎範例:

public class DeveloperAuthenticatedCredentials : CognitoAWSCredentials { const string PROVIDER_NAME = "example.com"; const string IDENTITY_POOL = "IDENTITY_POOL_ID"; static readonly RegionEndpoint REGION = RegionEndpoint.USEast1; private string login = null; public DeveloperAuthenticatedCredentials(string loginAlias) : base(IDENTITY_POOL, REGION) { login = loginAlias; } protected override async Task<IdentityState> RefreshIdentityAsync() { IdentityState state = null; //get your identity and set the state return state; } }

更新登入映射 (僅限 Android 和 iOS)

Android

在向您的身分驗證系統成功驗證使用者之後,請更新登入對應中的開發人員供應商名稱和開發使用者識別符。開發使用者識別符是英數字串,可唯一識別的身分驗證系統中的使用者。更新登入後,請務必呼叫 refresh方法,因為 identityId 對應可能有所變更:

HashMap<String, String> loginsMap = new HashMap<String, String>(); loginsMap.put(developerAuthenticationProvider.getProviderName(), developerUserIdentifier); credentialsProvider.setLogins(loginsMap); credentialsProvider.refresh();

iOS - Objective-C

除非沒有登入資料,或登入資料已過期,iOS 軟體開發套件才會呼叫 logins方法來取得最新的登入對應。如果您想要強制該軟體開發套件取得新的登入資料 (例如,最終使用者從未驗證變成已驗證,而您想要已驗證使用者的登入資料),請在 clearCredentials 上呼叫 credentialsProvider

[credentialsProvider clearCredentials];

iOS - Swift

除非沒有登入資料,或登入資料已過期,iOS 軟體開發套件才會呼叫 logins方法來取得最新的登入對應。如果您想要強制該軟體開發套件取得新的登入資料 (例如,最終使用者從未驗證變成已驗證,而您想要已驗證使用者的登入資料),請在 clearCredentials上呼叫 credentialsProvider

credentialsProvider.clearCredentials()

取得權杖 (伺服器端)

您可以透過呼叫 GetOpenIdTokenForDeveloperIdentity 來取得權杖。此 API 必須使用 AWS 開發人員登入資料從後端叫用。不得從用戶端軟體開發套件叫用。API 會收到 Cognito 身分池 ID、登入對應 (其中包含的索引鍵為您的身分供應商名稱,值為識別符),並選擇性地收到 Cognito 身分 ID (例如,您要使未驗證的使用者變成已驗證)。識別符可以是使用者的使用者名稱、電子郵件地址或數值。API 回應您的呼叫時,會包含您的使用者的唯一 Cognito ID,以及最終使用者的 OpenID Connect 權杖。

關於 GetOpenIdTokenForDeveloperIdentity傳回的權杖,請記得幾件事:

  • 您可以指定權杖的自訂過期時間,以便快取權杖。如果您未提供任何自訂過期時間,權杖是有效期限為 15 分鐘。

  • 您可以設定的權杖持續時間上限為 24 小時。

  • 請留意增加權杖持續時間的安全性影響。如果攻擊者取得此字符,他們可以在字符持續時間內將其交換為最終使用者的 AWS 憑證。

下列 Java 程式碼片段說明如何初始化 Amazon Cognito 用戶端,以及擷取開發人員驗證身分的權杖。

// authenticate your end user as appropriate // .... // if authenticated, initialize a cognito client with your AWS developer credentials AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient( new BasicAWSCredentials("access_key_id", "secret_access_key") ); // create a new request to retrieve the token for your end user GetOpenIdTokenForDeveloperIdentityRequest request = new GetOpenIdTokenForDeveloperIdentityRequest(); request.setIdentityPoolId("YOUR_COGNITO_IDENTITY_POOL_ID"); request.setIdentityId("YOUR_COGNITO_IDENTITY_ID"); //optional, set this if your client has an //identity ID that you want to link to this //developer account // set up your logins map with the username of your end user HashMap<String,String> logins = new HashMap<>(); logins.put("YOUR_IDENTITY_PROVIDER_NAME","YOUR_END_USER_IDENTIFIER"); request.setLogins(logins); // optionally set token duration (in seconds) request.setTokenDuration(60 * 15l); GetOpenIdTokenForDeveloperIdentityResult response = identityClient.getOpenIdTokenForDeveloperIdentity(request); // obtain identity id and token to return to your client String identityId = response.getIdentityId(); String token = response.getToken(); //code to return identity id and token to client //...

按照上述步驟,您應該能夠將開發人員驗證的身分整合在您的應用程式。如果您有任何問題,請隨時張貼在我們的論壇中。

連接至現有的社交身分

當您使用開發人員驗證的身分時,供應商的所有連結都必須從您的後端完成。若要將自訂身分連接至使用者的社交身分 (Login with Amazon、Sign in with Apple、Facebook 或 Google),請在呼叫 GetOpenIdTokenForDeveloperIdentity 時,將身分提供者權杖新增至呼叫對應。為了做到這一點,當您從用戶端軟體開發套件呼叫後端來驗證最終使用者時,請另外傳遞最終使用者的社交供應商權杖。

例如,如果您嘗試將自訂身分連結至 Facebook,當您呼叫 GetOpenIdTokenForDeveloperIdentity時,除了身分提供者識別符,也要將 Facebook 權杖新增至登入對應。

logins.put("YOUR_IDENTITY_PROVIDER_NAME","YOUR_END_USER_IDENTIFIER"); logins.put("graph.facebook.com","END_USERS_FACEBOOK_ACCESSTOKEN");

支援供應商之間的轉換

Android

您的應用程式可能需要支援未驗證的身分或使用公有身分供應商 (Login with Amazon、Sign in with Apple、Facebook 或 Google) 驗證的身分,以及開發人員驗證的身分。開發人員驗證的身分與其他身分 (未驗證的身分和使用公有供應商驗證的身分) 之間的基本差異,在於取得 identityId 和字符的方式。針對其他身分,行動應用程式會直接與 Amazon Cognito 互動,而不會聯絡您的身分驗證系統。所以行動應用程式應該能夠依據應用程式使用者的選擇,支援兩種不同的流程。因此,您必須對自訂身分供應商進行一些變更。

refresh 方法檢查登錄映射。如果映射不是空的,且擁有開發人員供應商名稱的金鑰,則會呼叫後端。否則,會呼叫 getIdentityId 方法並傳回無效值。

public String refresh() { setToken(null); // If the logins map is not empty make a call to your backend // to get the token and identityId if (getProviderName() != null && !this.loginsMap.isEmpty() && this.loginsMap.containsKey(getProviderName())) { /** * This is where you would call your backend **/ // now set the returned identity id and token in the provider update(identityId, token); return token; } else { // Call getIdentityId method and return null this.getIdentityId(); return null; } }

同樣地,依據登入對應的內容,getIdentityId方法也會有兩個流程:

public String getIdentityId() { // Load the identityId from the cache identityId = cachedIdentityId; if (identityId == null) { // If the logins map is not empty make a call to your backend // to get the token and identityId if (getProviderName() != null && !this.loginsMap.isEmpty() && this.loginsMap.containsKey(getProviderName())) { /** * This is where you would call your backend **/ // now set the returned identity id and token in the provider update(identityId, token); return token; } else { // Otherwise call &COG; using getIdentityId of super class return super.getIdentityId(); } } else { return identityId; } }

iOS - Objective-C

您的應用程式可能需要支援未驗證的身分或使用公有身分供應商 (Login with Amazon、Sign in with Apple、Facebook 或 Google) 驗證的身分,以及開發人員驗證的身分。若要這麼做,請覆寫 AWSCognitoCredentialsProviderHelper logins 方法,使其能夠依據目前的身分供應商,傳回正確的登入對應。此範例說明如何在未驗證、Facebook 和開發人員驗證的身分之間轉換。

- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins { if(/*logic to determine if user is unauthenticated*/) { return [AWSTask taskWithResult:nil]; }else if (/*logic to determine if user is Facebook*/){ return [AWSTask taskWithResult: @{ AWSIdentityProviderFacebook : [FBSDKAccessToken currentAccessToken] }]; }else { return [super logins]; } }

當您從未驗證轉換至已驗證時,應呼叫 [credentialsProvider clearCredentials];,以強制軟體開發套件取得新的已驗證登入資料。如果您在兩個已驗證的供應商之間切換,而不嘗試將這兩個供應商連結 (例如,您不要在登入字典中提供多個供應商的權杖),則應呼叫 [credentialsProvider clearKeychain];。這樣會同時清除登入資料和身分,並強制軟體開發套件取得新的登入資料和身分。

iOS - Swift

您的應用程式可能需要支援未驗證的身分或使用公有身分供應商 (Login with Amazon、Sign in with Apple、Facebook 或 Google) 驗證的身分,以及開發人員驗證的身分。若要這麼做,請覆寫 AWSCognitoCredentialsProviderHelper logins 方法,使其能夠依據目前的身分供應商,傳回正確的登入對應。此範例說明如何在未驗證、Facebook 和開發人員驗證的身分之間轉換。

override func logins () -> AWSTask<NSDictionary> { if(/*logic to determine if user is unauthenticated*/) { return AWSTask(result:nil) }else if (/*logic to determine if user is Facebook*/){ if let token = AccessToken.current?.authenticationToken { return AWSTask(result: [AWSIdentityProviderFacebook:token]) } return AWSTask(error:NSError(domain: "Facebook Login", code: -1 , userInfo: ["Facebook" : "No current Facebook access token"])) }else { return super.logins() } }

當您從未驗證轉換至已驗證時,應呼叫 credentialsProvider.clearCredentials(),以強制軟體開發套件取得新的已驗證登入資料。如果您在兩個已驗證的供應商之間切換,而不嘗試將這兩個供應商連結 (也就是說,您不要在登入字典中提供多個供應商的權杖),則應呼叫 credentialsProvider.clearKeychain()。這樣會同時清除登入資料和身分,並強制軟體開發套件取得新的登入資料和身分。

Unity

您的應用程式可能需要支援未驗證的身分或使用公有身分供應商 (Login with Amazon、Sign in with Apple、Facebook 或 Google) 驗證的身分,以及開發人員驗證的身分。開發人員驗證的身分與其他身分 (未驗證的身分和使用公有供應商驗證的身分) 之間的基本差異,在於取得 identityId 和字符的方式。針對其他身分,行動應用程式會直接與 Amazon Cognito 互動,而不會聯絡您的身分驗證系統。行動應用程式應該能夠依據應用程式使用者的選擇,支援兩種不同的流程。因此,您必須對自訂身分供應商進行一些變更。

在 Unity 中,建議的作法是從 AmazonCognitoEnhancedIdentityProvide (而不是從 AbstractCognitoIdentityProvider) 擴展您的身分提供者,並呼叫父系 RefreshAsync 方法 (而不是自己的方法),以免使用者未向您自己的後端驗證身分。如果使用者已驗證,則您可以使用先前說明的相同流程。

Xamarin

您的應用程式可能需要支援未驗證的身分或使用公有身分供應商 (Login with Amazon、Sign in with Apple、Facebook 或 Google) 驗證的身分,以及開發人員驗證的身分。開發人員驗證的身分與其他身分 (未驗證的身分和使用公有供應商驗證的身分) 之間的基本差異,在於取得 identityId 和字符的方式。針對其他身分,行動應用程式會直接與 Amazon Cognito 互動,而不會聯絡您的身分驗證系統。行動應用程式應該能夠依據應用程式使用者的選擇,支援兩種不同的流程。因此,您必須對自訂身分供應商進行一些變更。