devqon
devqon

Reputation: 13997

OAuth token bearer extra user information

I am using Web API secured with OAuth Bearer token. When getting the token I want to send extra information to the user, so I tried the following as per this thread:

CustomOAuthProvider.cs:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    // Other stuff, cut off for brevity

    var user = await userManager.FindAsync(context.UserName, context.Password);

    ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
    oAuthIdentity.AddClaims(ExtendedClaimsProvider.GetClaims(user));
    oAuthIdentity.AddClaims(RolesFromClaims.CreateRolesBasedOnClaims(oAuthIdentity));

    var ticket = new AuthenticationTicket(oAuthIdentity, this.CreateProperties(user.UserName, oAuthIdentity));

    context.Validated(ticket);
}

private AuthenticationProperties CreateProperties(string userName, ClaimsIdentity oAuthIdentity)
{
    var data = new Dictionary<string, string>
    {
        { "username", userName },
        { "roles", JsonConvert.SerializeObject(oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray()) }
    };
    return new AuthenticationProperties(data);
}

But the returned object is always as following:

{
    access_token: "theTokenHash"
    expires_in: 86399
    token_type: "bearer"
}

This is my Startup.cs:

public void Configuration(IAppBuilder app)
{
    // AutoMapper
    AutoMapperConfig.RegisterMappings();

    var httpConfig = new HttpConfiguration();

    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

    ConfigureOAuthTokenGeneration(app);
    ConfigureOAuthTokenConsumption(app);
    ConfigureWebApi(httpConfig);

    WebApiConfig.Register(httpConfig);
    AutofacConfig.Register(httpConfig);

    app.UseWebApi(httpConfig);

    httpConfig.EnsureInitialized();
}

private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
    // Configure the db context and user manager to use a single instance per request
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

    var OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        //For Dev enviroment only (on production should be AllowInsecureHttp = false)
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/oauth/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = new CustomOAuthProvider(),
        AccessTokenFormat = new CustomJwtFormat("http://localhost:59822")
    };

    // OAuth 2.0 Bearer Access Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

What am I doing wrong here?

Upvotes: 1

Views: 248

Answers (1)

devqon
devqon

Reputation: 13997

Wow never mind, I dug into the full example given in the answer of the link. It seems that adding the extra fields isn't enough. You still have to add the parameters to the context yourself by overriding the TokenEndpoint function:

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }
    return Task.FromResult<object>(null);
}

Upvotes: 1

Related Questions