beewest
beewest

Reputation: 4856

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?

Upvotes: 4

Views: 2217

Answers (2)

Jason
Jason

Reputation: 2617

A simple solution to this (in .NET 5 at least) is to set the RoleClaimType property in the services.AddJwtBearer TokenValidationParameters options.

services
    .AddAuthentication(options => 
    {
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters 
        { 
            ValidateAudience = false,
            RoleClaimType = "cognito:groups"
        };
        ...
    });

Upvotes: 2

beewest
beewest

Reputation: 4856

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    ;
        }

Upvotes: 3

Related Questions