Identidades autenticadas por desenvolvedor (grupos de identidades)
O Amazon Cognito oferece suporte a identidades autenticadas pelo desenvolvedor, além da federação de identidades da Web por meio de Facebook (grupos de identidades), Google (grupos de identidades), Login with Amazon (grupos de identidades) e Sign in with Apple (grupos de identidades). Com as identidades autenticadas pelos desenvolvedores, você pode registrar e autenticar usuários por meio do seu próprio processo de autenticação existente, sem deixar de usar o Amazon Cognito para sincronizar os dados do usuário e acessar os recursos da AWS. O uso de identidades autenticadas pelo desenvolvedor engloba a interação entre o dispositivo do usuário final, o backend para autenticação e o Amazon Cognito. Para obter mais detalhes, consulte Understanding Amazon Cognito Authentication Part 2: Developer Authenticated Identities
Como entender o fluxo de autenticação
Para obter informações sobre as identidades autenticadas pelo desenvolvedor e como elas diferem do fluxo de autenticação do provedor externo, consulte Fluxo de autenticação dos grupos de identidades (identidades federadas).
Defina um nome de provedor do desenvolvedor e associe-o a um grupo de identidades
Importante
Atualmente, os grupos de identidades do Amazon Cognito usam uma versão mais antiga do console do Amazon Cognito. Escolha Identidades federadas para navegar até o console de grupos de identidades.
Para usar identidades autenticadas pelo desenvolvedor, você precisará de um grupo de identidades associado ao seu provedor de desenvolvedor. Para fazer isso, siga estas etapas:
-
Faça login no console do Amazon Cognito
. -
Crie um novo grupo de identidades e, como parte do processo, defina um nome de provedor de desenvolvedor na guia Custom em Authentication Providers.
-
Se desejar, edite um grupo de identidades existente e defina um nome de provedor de desenvolvedor na guia Custom em Authentication Providers.
Observação: depois que o nome do provedor for definido, ele não poderá ser alterado.
Para obter instruções adicionais sobre como trabalhar com o console do Amazon Cognito, consulte Como usar o console do Amazon Cognito.
Implementar um provedor de identidade
Android
Para usar as identidades autenticadas pelo desenvolvedor, implemente sua própria classe de provedor de identidade, que estende AWSAbstractCognitoIdentityProvider
. A classe de provedor de identidade deve retornar um objeto de resposta contendo o token como um atributo.
Abaixo está um exemplo simples de um provedor de identidade.
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; } } }
Para usar esse provedor de identidade, você precisa inseri-lo em CognitoCachingCredentialsProvider
. Veja um exemplo abaixo:
DeveloperAuthenticationProvider developerProvider = new DeveloperAuthenticationProvider( null, "IDENTITYPOOLID", context, Regions.USEAST1); CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider( context, developerProvider, Regions.USEAST1);
iOS - objective-C
Para usar as identidades autenticadas pelo desenvolvedor, implemente sua própria classe de provedor de identidade, que estende 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
Para usar esse provedor de identidade, insira-o em AWSCognitoCredentialsProvider
, conforme mostrado no exemplo a seguir:
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];
Para oferecer suporte a identidades não autenticadas e identidades autenticadas pelo desenvolvedor, substitua o método logins
na implementação de AWSCognitoCredentialsProviderHelper
.
- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins { if(/*logic to determine if user is unauthenticated*/) { return [AWSTask taskWithResult:nil]; }else{ return [super logins]; } }
Para oferecer suporte a identidades autenticadas pelo desenvolvedor e provedores de redes sociais, gerencie o provedor atual da implementação logins
de AWSCognitoCredentialsProviderHelper
.
- (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
Para usar as identidades autenticadas pelo desenvolvedor, implemente sua própria classe de provedor de identidade, que estende 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) }
Para usar esse provedor de identidade, insira-o em AWSCognitoCredentialsProvider
, conforme mostrado no exemplo a seguir:
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
Para oferecer suporte a identidades não autenticadas e identidades autenticadas pelo desenvolvedor, substitua o método logins
na implementação de AWSCognitoCredentialsProviderHelper
.
override func logins () -> AWSTask<NSDictionary> { if(/*logic to determine if user is unauthenticated*/) { return AWSTask(result:nil) }else { return super.logins() } }
Para oferecer suporte a identidades autenticadas pelo desenvolvedor e provedores de redes sociais, gerencie o provedor atual da implementação logins
de AWSCognitoCredentialsProviderHelper
.
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
Após obter um ID de identidade e um token de sessão no backend, você os inserirá no provedor AWS.CognitoIdentityCredentials
. Veja um exemplo abaixo:
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
Para usar identidades autenticadas pelo desenvolvedor, é necessário estender CognitoAWSCredentials
e substituir o método RefreshIdentity
para recuperar o ID de identidade e o token do usuário no back-end e retorná-los. Veja a seguir um exemplo simples de um provedor de identidade que entrará em contato com um back-end hipotético em "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); } }
O código acima usa um objeto dispatcher de thread para chamar uma corrotina. Se você não tem uma maneira de fazer isso no seu projeto, use o seguinte script em suas cenas:
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
Para usar identidades autenticadas pelo desenvolvedor, é necessário estender CognitoAWSCredentials
e substituir o método RefreshIdentity
para recuperar o ID de identidade e o token do usuário no back-end e retorná-los. Veja a seguir um exemplo simples de um provedor de identidade que entrará em contato com um back-end hipotético em "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; } }
Como atualizar o mapa de logins (apenas Android e iOS)
Android
Após autenticar o usuário com êxito por meio do sistema de autenticação, atualize o mapa de logins com o nome do provedor do desenvolvedor e um identificador de usuário do desenvolvedor, que é uma string alfanumérica que identifica exclusivamente um usuário no sistema de autenticação. Não deixe de chamar o método refresh
após a atualização do mapa de logins, pois identityId
pode ter sido alterado:
HashMap<String, String> loginsMap = new HashMap<String, String>(); loginsMap.put(developerAuthenticationProvider.getProviderName(), developerUserIdentifier); credentialsProvider.setLogins(loginsMap); credentialsProvider.refresh();
iOS - objective-C
O iOS SDK chama o método logins
apenas para obter o mapa de logins mais recente, caso não haja credenciais ou elas tenham expirado. Se você quiser forçar o SDK a obter novas credenciais (por exemplo, se o usuário final era não autenticado e se tornou autenticado, e você precisar das credenciais com base no usuário autenticado), chame clearCredentials
no credentialsProvider
.
[credentialsProvider clearCredentials];
iOS - swift
O iOS SDK chama o método logins
apenas para obter o mapa de logins mais recente, caso não haja credenciais ou elas tenham expirado. Se você quiser forçar o SDK a obter novas credenciais (por exemplo, se o usuário final era não autenticado e se tornou autenticado, e você precisar das credenciais com base no usuário autenticado), chame clearCredentials
no credentialsProvider
.
credentialsProvider.clearCredentials()
Como obter um token (lado do servidor)
Obtenha um token chamando GetOpenIdTokenForDeveloperIdentity. Essa API deve ser invocada do seu backend por meio das credenciais de desenvolvedor da AWS. Ele não deve ser invocada no SDK do cliente. A API recebe o ID do grupo de identidades do Cognito; um mapa de logins contendo o nome do provedor de identidade como chave e o identificador como valor; e, opcionalmente, o ID de identidade do Cognito (por exemplo, você está autenticando um usuário não autenticado). O identificador pode ser o nome de usuário do seu usuário, um endereço de e-mail ou um valor numérico. A API responde à chamada com um ID exclusivo do Cognito para o usuário e um token do OpenID Connect para o usuário final.
Tenha em mente as seguintes informações sobre o token retornado por GetOpenIdTokenForDeveloperIdentity
:
-
Você pode especificar um período de expiração personalizado para o token, a fim de que possa armazená-lo em cache. Se você não fornecer o período de expiração personalizado, o token ficará válido por 15 minutos.
-
A duração máxima do token que você pode definir é 24 horas.
-
Tenha em mente as implicações de segurança relacionadas ao aumento da duração do token. Se um invasor obtiver esse token, ele poderá trocá-lo pelas credenciais da AWS do usuário final enquanto o token estiver válido.
O trecho Java a seguir mostra como inicializar um cliente do Amazon Cognito e recuperar um token para uma identidade autenticada pelo desenvolvedor.
// 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 //...
Ao seguir as etapas acima, você será capaz de integrar as identidades autenticadas pelo desenvolvedor em seu aplicativo. Se você tiver problemas ou dúvidas, fique à vontade para publicar em nossos fóruns
Conectar-se a uma identidade social existente
Todos os vínculos de provedores durante o uso de identidades autenticadas pelo desenvolvedor devem ser feitos no backend. Para conectar uma identidade personalizada à identidade social de um usuário (Login with Amazon, Fazer login com a Apple, Facebook ou Google), adicione o token do provedor de identidade ao mapa de logins ao chamar GetOpenIdTokenForDeveloperIdentity. Para que isso seja possível, ao chamar o backend no SDK do cliente para autenticar o usuário final, insira também o token do provedor de redes sociais do usuário final.
Por exemplo, se você estiver tentando vincular uma identidade personalizada ao Facebook, adicione o token do Facebook, além do identificador do provedor de identidade, ao mapa de logins quando chamar GetOpenIdTokenForDeveloperIdentity
.
logins.put("YOUR_IDENTITY_PROVIDER_NAME","YOUR_END_USER_IDENTIFIER"); logins.put("graph.facebook.com","END_USERS_FACEBOOK_ACCESSTOKEN");
Dar suporte à transição entre provedores
Android
Talvez, seu aplicativo exija o suporte a identidades autenticadas ou não autenticadas por meio de provedores públicos (Login with Amazon, Fazer login com a Apple, Facebook ou Google), juntamente com as identidades autenticadas pelo desenvolvedor. A principal diferença entre as identidades autenticadas pelo desenvolvedor e outras identidades (identidades autenticadas e não autenticadas por meio do provedor público) é a maneira como o ID de identidade e o token são obtidos. Para outras identidades, a aplicação móvel interagirá diretamente com o Amazon Cognito, em vez de entrar em contato com o sistema de autenticação. Portanto, o aplicativo para dispositivos móveis deve ser capaz de oferecer suporte a dois fluxos distintos, dependendo da opção feita pelo usuário do aplicativo. Para isso, você precisará fazer algumas alterações no provedor de identidade personalizado.
O método refresh
verificará o mapa de logins, se o mapa não estiver vazio e tiver uma chave com o nome do provedor do desenvolvedor, e você chamará o backend; caso contrário, basta chamar o método getIdentityId e retornar nulo.
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; } }
Da mesma forma, o método getIdentityId
terá dois fluxos de acordo com o conteúdo do mapa de logins:
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
Talvez, seu aplicativo exija o suporte a identidades autenticadas ou não autenticadas por meio de provedores públicos (Login with Amazon, Fazer login com a Apple, Facebook ou Google), juntamente com as identidades autenticadas pelo desenvolvedor. Para fazer isso, substitua o método AWSCognitoCredentialsProviderHelperlogins
para poder retornar o mapa de logins correto com base no provedor de identidade atual. Este exemplo mostra como você pode alternar entre identidade não autenticada, Facebook e identidade autenticada pelo desenvolvedor.
- (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]; } }
Ao fazer a transição de não autenticada para autenticada, você deverá chamar [credentialsProvider clearCredentials];
para forçar o SDK a obter novas credenciais autenticadas. Quando você alternar entre dois provedores autenticados e estiver tentando vincular os dois provedores (ou seja, se você não estiver fornecendo tokens para vários provedores no dicionário de logins), chame [credentialsProvider
clearKeychain];
. Isso limpará as credenciais e a identidade, e forçará o SDK a obter novas.
iOS - swift
Talvez, seu aplicativo exija o suporte a identidades autenticadas ou não autenticadas por meio de provedores públicos (Login with Amazon, Fazer login com a Apple, Facebook ou Google), juntamente com as identidades autenticadas pelo desenvolvedor. Para fazer isso, substitua o método AWSCognitoCredentialsProviderHelperlogins
para poder retornar o mapa de logins correto com base no provedor de identidade atual. Este exemplo mostra como você pode alternar entre identidade não autenticada, Facebook e identidade autenticada pelo desenvolvedor.
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() } }
Ao fazer a transição de não autenticada para autenticada, você deverá chamar credentialsProvider.clearCredentials()
para forçar o SDK a obter novas credenciais autenticadas. Quando você alternar entre dois provedores autenticados e estiver tentando vincular os dois provedores (ou seja, se você não estiver fornecendo tokens para vários provedores no dicionário de logins), chame credentialsProvider.clearKeychain()
. Isso limpará as credenciais e a identidade, e forçará o SDK a obter novas.
Unity
Talvez, seu aplicativo exija o suporte a identidades autenticadas ou não autenticadas por meio de provedores públicos (Login with Amazon, Fazer login com a Apple, Facebook ou Google), juntamente com as identidades autenticadas pelo desenvolvedor. A principal diferença entre as identidades autenticadas pelo desenvolvedor e outras identidades (identidades autenticadas e não autenticadas por meio do provedor público) é a maneira como o ID de identidade e o token são obtidos. Para outras identidades, a aplicação móvel interagirá diretamente com o Amazon Cognito, em vez de entrar em contato com o sistema de autenticação. Portanto, o aplicativo para dispositivos móveis deve ser capaz de oferecer suporte a dois fluxos distintos, dependendo da opção feita pelo usuário do aplicativo. Para isso, você precisará fazer algumas alterações no provedor de identidade personalizado.
A forma recomendada de fazer isso no Unity é estendendo o provedor de identidade em AmazonCognitoEnhancedIdentityProvide, e não em AbstractCognitoIdentityProvider, e chamando o método pai RefreshAsync em vez de seu próprio método, caso o usuário não seja autenticado com seu próprio backend. Se o usuário estiver autenticado, use o mesmo fluxo descrito antes.
Xamarin
Talvez, seu aplicativo exija o suporte a identidades autenticadas ou não autenticadas por meio de provedores públicos (Login with Amazon, Fazer login com a Apple, Facebook ou Google), juntamente com as identidades autenticadas pelo desenvolvedor. A principal diferença entre as identidades autenticadas pelo desenvolvedor e outras identidades (identidades autenticadas e não autenticadas por meio do provedor público) é a maneira como o ID de identidade e o token são obtidos. Para outras identidades, a aplicação móvel interagirá diretamente com o Amazon Cognito, em vez de entrar em contato com o sistema de autenticação. Portanto, o aplicativo para dispositivos móveis deve ser capaz de oferecer suporte a dois fluxos distintos, dependendo da opção feita pelo usuário do aplicativo. Para isso, você precisará fazer algumas alterações no provedor de identidade personalizado.