How to customize ASP .NET Web API JWT token response?

I am using Asp.net Webform project with Web API. I configured JWT token-based authentication and now I want to customize the authentication response

Here are my configurations,

  1. Startup.cs
    public class Startup
    {
         public void Configuration(IAppBuilder app)
         {
             HttpConfiguration config = new HttpConfiguration();
    
             // Web API routes
             config.MapHttpAttributeRoutes();
    
             app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    
             ConfigureOAuth(app);
    
             app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    
             WebApiConfig.Register(config);
    
         }
    
         public void ConfigureOAuth(IAppBuilder app)
         {
    
             String apiHttpOnly = ConfigurationManager.AppSettings["AllowInsecureHttp"];
             String tokenTimeSpan = ConfigurationManager.AppSettings["tokenTimeSpanFromMinutes"];
    
             bool allowInsecureHttp = !String.IsNullOrEmpty(apiHttpOnly) ? 
                                      Convert.ToBoolean(apiHttpOnly) : false;
             int accessTokenExpireTimeSpan = !String.IsNullOrEmpty(tokenTimeSpan) ? 
                                      Convert.ToInt32(tokenTimeSpan) : 60;
    
             var authProvider = new AuthorizationServiceProvider();
             OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
             {
                 //For Dev enviroment only (on production should be AllowInsecureHttp = false)
                 AllowInsecureHttp = allowInsecureHttp,
                 TokenEndpointPath = new PathString("/api/authenticate"),
                 AccessTokenExpireTimeSpan = TimeSpan.FromDays(accessTokenExpireTimeSpan),
                 Provider = authProvider
             };
    
             app.UseOAuthAuthorizationServer(options);
    
         }
    }
  2. AuthorizationServiceProvider
     public class AuthorizationServiceProvider : OAuthAuthorizationServerProvider
     {
         public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
         {
             context.Validated();
             return base.ValidateClientAuthentication(context);
         }
    
         public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
         {
             var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    
             if (Membership.ValidateUser(context.UserName, context.Password))
             {
                 identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                 identity.AddClaim(new Claim("username", context.UserName));
                 identity.AddClaim(new Claim(ClaimTypes.Name, "admin admin"));
                 context.Validated(identity);
             }
             else
             {
                 context.SetError("invalid_grant", "Provide username and password is incorrect.");
    
             }
    
             return base.GrantResourceOwnerCredentials(context);
         }
     }

When I call the API with the right credentials, it returns like

{
    "access_token": "uEwmXl6N0mJXVUZesxA_2tG5lIuZUIUDaxtjAl0QGE6j2-J7n4c63zboOUClGjRQf1IDY9-nBgyq0HP5WR7MMxTYoHGIyiHIbcKu9AYwhECCGaVBCxY2Ounhit4N1pYK1vV6uX6AcoA-a0xhytF8Jz27D77ZvCLi3PuUQDEXSp0pkGG796wu1fRZCaRsCB-kLoa-_V7KJaGGhhoybN_c0GNOBhhwmGpx6Js26-Vx-lmWpfsPUE1aKrJfx-oMcyE5x7CooAlx4vA6iZhnNfmYdRejRKoKKnObyuAsym7mVdZY3bpv",
    "token_type": "bearer",
    "expires_in": 5183999
}

I want to customize the response by adding some extra attributes like,
{
    "access_token": "uEwmXl6N0mJXVUZesxA_2tG5lIuZUIUDaxtjAl0QGE6j2-J7n4c63zboOUClGjRQf1IDY9-nBgyq0HP5WR7MMxTYoHGIyiHIbcKu9AYwhECCGaVBCxY2Ounhit4N1pYK1vV6uX6AcoA-a0xhytF8Jz27D77ZvCLi3PuUQDEXSp0pkGG796wu1fRZCaRsCB-kLoa-_V7KJaGGhhoybN_c0GNOBhhwmGpx6Js26-Vx-lmWpfsPUE1aKrJfx-oMcyE5x7CooAlx4vA6iZhnNfmYdRejRKoKKnObyuAsym7mVdZY3bpv",
    "token_type": "bearer",
    "expires_in": 5183999,
    "attribute1" : "abc",
    "attribute2" : "ert"
}

Anyone have an idea to do that?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Finally, I investigate the problem and find out the solution. I posted it here, maybe it may help someone.

  1. Add AuthenticationProperties
    var props = new AuthenticationProperties(new Dictionary<string, string>
    {
        {
             "attribute1" , "abc"
        },
        {
             "attribute2" , "ert"
        }
    });
  2. Then create Ticket using AuthenticationTicket
    var ticket = new AuthenticationTicket(identity, props);
  3. Add ticket to the context
    context.Validated(ticket);
  4. Then implement the override method TokenEndpoint
     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);
     }

Finally AuthorizationServiceProvider class be like,

public class AuthorizationServiceProvider : OAuthAuthorizationServerProvider
{
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
        return base.ValidateClientAuthentication(context);
    }

    public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);

        if (string.IsNullOrEmpty(context.UserName) || string.IsNullOrEmpty(context.Password))
        {
            context.SetError("invalid_request", "No username or password are provided.");
        }
        else if (Membership.ValidateUser(context.UserName, context.Password))
        {
            
            identity.AddClaim(new Claim("username", context.UserName));
            identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));

            /*
             * All custom response props are define here.
             * --------usage----------
             * use as dictionary
             * */
            var props = new AuthenticationProperties(new Dictionary<string, string>
            {
                //{
                //    "test" , "val"
                //}
            });

            var ticket = new AuthenticationTicket(identity, props);


            context.Validated(ticket);
        }
        else
        {
            context.SetError("invalid_grant", "Provide username and password is incorrect.");

        }

        return base.GrantResourceOwnerCredentials(context);
    }

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

For more info – https://stackoverflow.com/a/26369622/8403632

Sample Example – https://github.com/Leftyx/OwinWebApiBearerToken


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x