amazon-web-servicesasp.net-core-webapiamazon-cognitorole-based-access-control

generate role-based claims for aws cognito id token


Authenticate with AWS Cognito, I can get ID token including cognito:groups { admin, user}. From ASPNetCore Webapi, I can authorize using Policy (folows AWS tutorial https://www.youtube.com/watch?v=M6qTrI7kmZk):

services.AddSingleton<IAuthorizationHandler, CognitoGroupAuthorizationHandler>();
        services.AddAuthorization(options=> {
            options.AddPolicy("admin", p => p.Requirements.Add(
                new CognitoGroupAuthorizationRequirement("admin")
                ));
            options.AddPolicy("user", p => p.Requirements.Add(
                new CognitoGroupAuthorizationRequirement("user")
                ));
        });            

It works when declaring Policy in my Controller [Authorize(Policy = "admin")]. However my api uses roles instead.

Any way to do with [Authorize(Role = "admin")] please?


Solution

  • Transform cognito group into claim role using IClaimsTransformation:

    public class ClaimsTransformer : IClaimsTransformation
        {
            public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
            {
                var claims = new List<Claim>();
    
                var cognitoClaims = principal.Claims.Where(t => t.Type == "cognito:groups").ToList();
                foreach (var claim in cognitoClaims)
                {
                    var claim2 = new Claim(ClaimTypes.Role, claim.Value);
                    claims.Add(claim2);
                }
    
                var claimsIdentity = new ClaimsIdentity(claims, IdentityConstants.ApplicationScheme);
    
                return new ClaimsPrincipal(claimsIdentity);
            }
        }
    

    Register in into Startup\ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
            {
    
                // Adds Amazon Cognito as Identity Provider
                //services.AddCognitoIdentity();
    
                services.AddAuthentication("Bearer")
                .AddJwtBearer(options =>
                {
                    options.Audience = "aws-app-client-id";
                    options.Authority = "https://cognito-idp.us-east-1.amazonaws.com/aws-pool-id";
                });
    
                services.AddScoped<IClaimsTransformation, ClaimsTransformer>();
    
                services.AddControllers();
            }
    

    The token is generated by cognito username and password:

    [HttpGet]
            [Route("{username}/{password}")]
            public async Task<string> Get(string username, string password)
            {
                var provider = new AmazonCognitoIdentityProviderClient(RegionEndpoint.USEast1);
    
                var pool = new CognitoUserPool(poolId, clientId, provider);
    
                var user = new CognitoUser(userId, clientId, pool, provider);
    
                var request = new InitiateSrpAuthRequest
                {
                    Password="cognito-password"
                };
    
                AuthFlowResponse response = await user.StartWithSrpAuthAsync(request);
    
    
                return response.AuthenticationResult.IdToken    ;
            }