Use Toker Token authentication for API and OpenId authentication for MVC in the same application project

I am trying to use OpenId authentication and Bearer token in my application via Identity Server.

The problem currently is that once I have authenticated the user, I still need to get the bearer token in order to be able to call any action methods for my ASP.NET MVC application.

Here is my boot file for the app

 public class Startup
{
     public void Configuration(IAppBuilder app)
     {            
         AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
         JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
            AuthenticationType = "Cookies"
         });

         app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
         {
            Authority = "https://localhost:44301/identity",
            ClientId = "baseballStats",
            Scope = "openid profile roles baseballStatsApi",
            RedirectUri = "https://localhost:44300/",
            ResponseType = "id_token token",
            SignInAsAuthenticationType = "Cookies",
            UseTokenLifetime = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = async n =>
                {
                    var userInfoClient = new UserInfoClient(
                                 new Uri(n.Options.Authority + "/connect/userinfo"),
                                 n.ProtocolMessage.AccessToken);

                    var userInfo = await userInfoClient.GetAsync();

                    // create new identity and set name and role claim type
                    var nid = new ClaimsIdentity(
                       n.AuthenticationTicket.Identity.AuthenticationType,
                        Constants.ClaimTypes.GivenName,
                        Constants.ClaimTypes.Role);

                    userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));

                    // keep the id_token for logout
                    nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                    // add access token for sample API
                    nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                    // keep track of access token expiration
                    nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                    // add some other app specific claim
                    nid.AddClaim(new Claim("app_specific", "some data"));

                    n.AuthenticationTicket = new AuthenticationTicket(
                        nid,
                        n.AuthenticationTicket.Properties);
                }
            }
         });



         app.UseResourceAuthorization(new AuthorizationManager());

         app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
         {
             Authority = "https://localhost:44301/identity",
             RequiredScopes = new[] { "baseballStatsApi" }
         });

         var config = new HttpConfiguration();
         config.MapHttpAttributeRoutes();
         app.UseWebApi(config);           
     }
}

      

I would like to restrict the bearer token authentication to my api addresses only and use openID authentication again. Is there a way to do this?

+3


source to share


1 answer


Ok I found some information on the following post

https://github.com/IdentityServer/IdentityServer3/issues/487

A github repository implementing the concepts discussed in the link can be found here

https://github.com/B3nCr/IdentityServer-Sample/blob/master/B3nCr.Communication/Startup.cs



Basically you need to map api url to other config using app.Map (). In my case, I changed the startup file this way.

 public class Startup
{
     public void Configuration(IAppBuilder app)
     {
         AntiForgeryConfig.UniqueClaimTypeIdentifier = Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Subject;
         JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
             AuthenticationType = "Cookies"
         });

         var openIdConfig = new OpenIdConnectAuthenticationOptions
         {
             Authority = "https://localhost:44301/identity",
             ClientId = "baseballStats",
             Scope = "openid profile roles baseballStatsApi",
             RedirectUri = "https://localhost:44300/",
             ResponseType = "id_token token",
             SignInAsAuthenticationType = "Cookies",                 
             UseTokenLifetime = false,
             Notifications = new OpenIdConnectAuthenticationNotifications
             {
                 SecurityTokenValidated = async n =>
                 {
                     var userInfoClient = new UserInfoClient(
                                  new Uri(n.Options.Authority + "/connect/userinfo"),
                                  n.ProtocolMessage.AccessToken);

                     var userInfo = await userInfoClient.GetAsync();

                     // create new identity and set name and role claim type
                     var nid = new ClaimsIdentity(
                        n.AuthenticationTicket.Identity.AuthenticationType,
                         Thinktecture.IdentityServer.Core.Constants.ClaimTypes.GivenName,
                         Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Role);

                     userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));

                     // keep the id_token for logout
                     nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                     // add access token for sample API
                     nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                     // keep track of access token expiration
                     nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                     // add some other app specific claim
                     nid.AddClaim(new Claim("app_specific", "some data"));

                     n.AuthenticationTicket = new AuthenticationTicket(
                         nid,
                         n.AuthenticationTicket.Properties);

                     n.Request.Headers.SetValues("Authorization ", new string[] { "Bearer ", n.ProtocolMessage.AccessToken });
                 }
             }
         };

         app.UseOpenIdConnectAuthentication(openIdConfig);

         app.UseResourceAuthorization(new AuthorizationManager());

         app.Map("/api", inner =>
         {
             var bearerTokenOptions = new IdentityServerBearerTokenAuthenticationOptions
             {
                 Authority = "https://localhost:44301/identity",
                 RequiredScopes = new[] { "baseballStatsApi" }
             };

             inner.UseIdentityServerBearerTokenAuthentication(bearerTokenOptions);
             var config = new HttpConfiguration();
             config.MapHttpAttributeRoutes();
             inner.UseWebApi(config);
         });                                                 
     }
}

      

This solved my problem. I can now access the MVC pages using cookie based authentication and call the API with bearer token authentication.

+6


source







All Articles