【问题标题】:Amazon Cognito Identity with API Gateway带有 API 网关的 Amazon Cognito 身份
【发布时间】:2021-03-05 10:28:50
【问题描述】:

我正在使用 Xamarin 跨平台开发应用程序 IOS 和 Android。 我正在努力使用从 Cognito Identity 接收的凭据来授权应用调用 API Gateway。

我的用户流是:

  1. 在 Cognito 用户池上进行身份验证并获取令牌
  2. 用令牌交换 Cognito 身份池上的凭据
  3. 使用在上一步中检索到的凭据访问 API Gateway。

第 1 步和第 2 步似乎工作正常。但是当应用程序尝试连接到 api 网关时,它会收到错误 403 (Forbidden)。

我的代码:

  1. 在 Cognito 用户池上进行身份验证并获取令牌

**

public async Task<AppUser> Login(string username, string password)   
 {
        CognitoUser cognitoUser = new CognitoUser(username, Aws.COGNITO_CLIENT_ID, CognitoUserPool, CognitoIdentityProviderClient);
        AppUser appUser = new AppUser() { Email = username };
        // Send a login request and wait for the response from Amazon
        try
        {
            AuthFlowResponse response = await cognitoUser.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
            {                    
                Password = password
            });
            ;
            appUser.IsAuthenticated = true;
        }
        catch (NotAuthorizedException e)
        {
            appUser.IsAuthenticated = false;
            appUser.ErrorMessage = e.Message;
        }
        await _tokenManagement.SaveTokens(cognitoUser.SessionTokens) ;
        return appUser;
    }
  1. 用令牌交换 Cognito 身份池上的凭据

**

public async Task<ImmutableCredentials> GetAppCredentialsAsync()
{
    CognitoAWSCredentials cac;
        
        if (_tokenManagement.CheckIsAnonymous())
        {
            //Anonymous credentials        
            cac = new CognitoAWSCredentials(Aws.COGINITO_IDENTITY_POLL_ID, RegionEndpoint.USEast1); 
        }
        else
        {
            //Retrieve saved tokens from previous authentication
            var tm = await _tokenManagement.RetrieveTokens();
        
            CognitoUser user = new CognitoUser(null, Aws.COGNITO_CLIENT_ID, CognitoUserPool, CognitoIdentityProviderClient)
            {
                    SessionTokens = new CognitoUserSession(tm.IdToken, tm.AccessToken, tm.RefreshToken, tm.IssuedTime, tm.ExpirationTime)
            };
            //Retrieve authenticated credentials
            cac = user.GetCognitoAWSCredentials(Aws.COGINITO_IDENTITY_POLL_ID, RegionEndpoint.USEast1);
        
        }
                       
     }
                 
    return await cac.GetCredentialsAsync();
        
}
  1. 使用在上一步中检索到的凭据访问 API Gateway:

**

public async Task<IList<MediaImage>> GetCoversAWSAsync()
    {
        // Getting credentials and sign request
        var request = await BuildRequestAsync("/listMedia");
        
        var client = new HttpClient();
        
        var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
    
        IList<MediaImage> covers = JsonConvert.DeserializeObject<IList<MediaImage>>(await response.Content.ReadAsStringAsync());
    
        return covers;
    
    }
    
    private async Task<HttpRequestMessage> BuildRequestAsync(string service)
    {
    
        var request = new HttpRequestMessage()
        {
            Method = HttpMethod.Get,
            RequestUri = new Uri(baseURL + service)
            
        };   
        
        ImmutableCredentials awsCredential = await _loginService.GetAppCredentialsAsync( );
                       
    
        var signer = new AWS4RequestSigner(awsCredential.AccessKey, awsCredential.SecretKey);
    
        request = await signer.Sign(request, "execute-api", awsRegion);
    
    
        return request;
    
    }

当我硬编码来自一个 IAM 用户的凭据时,此代码可以正常工作。但是从 Cognito Identities 检索到的凭据却出现了 Forbidden 错误。 我使用 SDK for S3 进行了测试,我能够成功列出具有从 Cognito Identities 接收到的相同凭据的存储桶,但无法在 API 网关上发出请求。

你能帮帮我吗?我在哪里迷路了?

【问题讨论】:

    标签: amazon-web-services aws-api-gateway amazon-cognito aws-sdk-net


    【解决方案1】:

    我知道发生了什么。

    在确保 AWS 上的权限设置正确之后。

    我在文档中发现有必要在 HTTP 标头中包含 cognito 返回的令牌(标头名称 x-amz-security-token)。于是我把代码改成如下:

        private async Task<HttpRequestMessage> BuildRequestAsync(string service)
        {
        
            var request = new HttpRequestMessage()
            {
                Method = HttpMethod.Get,
                RequestUri = new Uri(baseURL + service)
                
            };   
            
            ImmutableCredentials awsCredential = await _loginService.GetAppCredentialsAsync( );
    
            //This where I add header to the HTTP request              
            request.Headers.Add("x-amz-security-token", awsCredential.Token);
    
            var signer = new AWS4RequestSigner(awsCredential.AccessKey, awsCredential.SecretKey);
        
            request = await signer.Sign(request, "execute-api", awsRegion);
        
        
            return request;
        
        }
    

    【讨论】:

      猜你喜欢
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      • 2016-12-25
      • 2017-10-25
      • 2016-05-26
      • 2017-04-08
      • 2017-03-25
      相关资源
      最近更新 更多