Quantcast
Channel: ASP.NET Core
Viewing all articles
Browse latest Browse all 9386

IdentityServer : redirection problem and custom claims

$
0
0

Hi,

Following the instructions provided to implement IdentityServer, I managed to achieve the following points (my code is based on https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/Combined_AspNetIdentity_and_EntityFrameworkStorage):

Here are all involved local web sites:

> localhost:5000 (Master web app - Identity & Identity server - Bearer authority for API)

> localhost:5001 (Slave 1 web app - Host API that need Bearer Auth from Master web app)

> localhost:5002 (Slave 2 web app - web site that is supposed to share the same authentication from IdentityServer redirecting on Master web app login page if needed)

Here are the achieved points :

  • Have the Master web app, using Identity within a database (Postgres), and being itself the authority for external clients using a Bearer authentication (API consumption)
  • External clients (Postman) manages to reach a third party API (web App Slave 2) using the bearer token provided by theMaster web app which is here the Autority
  • External clients (Postman) manages to reach an API hosted inMaster web App using the bearer token provided by the Master web app itself  which is here its self Autority

Here are the blocking points :

1) I would like to add custom claims within the JWT token, the claims should be based on user information (I use the ResourceOwner method), like email, Name etc ... I folllowed this topic : http://docs.identityserver.io/en/release/topics/resources.html but the claims defined in customProfile are not supplied back within the Token. 

Here is my Config.cs in Master web app

        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            var customProfile = new IdentityResource(
                name: "my.profile",
                displayName: "My profile",
                claimTypes: new[] { ClaimTypes.Name, "FirstName","email"}); // These claims are fed for each logged user

            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                customProfile
            };
        }

Here is the action from Slave 1 web that requires a JWT auth

    [Route("[controller]")]
    [Authorize]
    public class IdentityController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    }

third party API

Here are the claims get from Bearer token on Slave 1 web app previous Identity controller and action Get => no custom claims appears here (Name, Firstname, email) !

[
    {"type": "nbf","value": "1511442654"
    },
    {"type": "exp","value": "1511446254"
    },
    {"type": "iss","value": "http://localhost:5000"
    },
    {"type": "aud","value": "http://localhost:5000/resources"
    },
    {"type": "aud","value": "api1"
    },
    {"type": "client_id","value": "ro.client"
    },
    {"type": "sub","value": "3977615f-ad7d-425d-8f5e-693705d0184f"
    },
    {"type": "auth_time","value": "1511442654"
    },
    {"type": "idp","value": "local"
    },
    {"type": "scope","value": "api1"
    },
    {"type": "amr","value": "pwd"
    }
]

2) I'm not able to access my Slave 2 web app [Authorize] actions where this web app as declared Master web app as authority. I don't use Bearer auth here, I just get on the action using any browser, which redirect me corretly (seeing 302 redirection on brower) on my Master web app login page.

I log in, then I get a 404 error page, and I never get redirected to the original requested page on Slave 2 web app

Here is the requested action from Slave 2 web app 

        [Authorize]
        public IActionResult Secure()
        {
            ViewData["Message"] = "Secure page.";

            return View();

And the redirection :

redirect login

Then I log in => it fails indicating a 404 error instead of reaching the original route:

redriect after log in

Thanks to anyone who could help!

Nicolas

Finaly here my codes for :

Master web app startup.cs :

*** ConfigureServices ***  
services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(Configuration.GetConnectionString("PostgreSQLConnection"))); services.AddIdentity<ApplicationUser, IdentityRole>(config => { config.SignIn.RequireConfirmedEmail = true; config.Password.RequireDigit = true; config.Password.RequireLowercase = false; config.Password.RequireUppercase = false; config.Password.RequireNonAlphanumeric = false; config.Password.RequiredLength = 6; }) .AddEntityFrameworkStores<ApplicationDbContext>() .AddErrorDescriber<CustomIdentityErrorDescriber>() .AddDefaultTokenProviders();

string connectionString = Configuration.GetConnectionString("PostgreSQLConnection"); var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; // configure identity server with in-memory stores, keys, clients and scopes services.AddIdentityServer() .AddDeveloperSigningCredential() .AddAspNetIdentity<ApplicationUser>() // this adds the config data from DB (clients, resources) .AddConfigurationStore(options => { options.ConfigureDbContext = builder => builder.UseNpgsql(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }) // this adds the operational data from DB (codes, tokens, consents) .AddOperationalStore(options => { options.ConfigureDbContext = builder => builder.UseNpgsql(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; options.TokenCleanupInterval = 30; });


services.AddMvcCore() .AddAuthorization() .AddJsonFormatters(); services.AddAuthentication();

services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { options.Authority = "http://localhost:5000";// Master web app itself ! options.RequireHttpsMetadata = false; options.ApiName = "api1"; });

*** Configure
app.UseIdentityServer();

Master web app Config.cs :

 public class Config
    {

        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            var customProfile = new IdentityResource(
                name: "my.profile",
                displayName: "My profile",
                claimTypes: new[] { ClaimTypes.Name, "FirstName","email"});

            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                customProfile
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "My API")
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            // client credentials client
            return new List<Client>
            {
                new Client
                {
                    ClientId = "client",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" }
                },

                // resource owner password grant client
                new Client
                {
                    ClientId = "ro.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" }
                },

                // OpenID Connect hybrid flow and client credentials client (MVC)
                new Client
                {
                    ClientId = "mvc",
                    ClientName = "MVC Client",
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                    RequireConsent = true,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },

                    RedirectUris = { "http://localhost:5002/signin-oidc" }, // Slave 2 web app
                    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },  Slave 2 web app
AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1" }, AllowOfflineAccess = true } }; } }

Slave 1 web app startup.cs :

*** ConfigureServices ***
services.AddMvcCore() .AddAuthorization() .AddJsonFormatters(); services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { options.Authority = "http://localhost:5000"; // Master web app options.RequireHttpsMetadata = false; options.ApiName = "api1"; });

Slave 2 web app startup.cs :

*** ConfigureServices *** 
services.AddMvc(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.SignInScheme = "Cookies"; options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.ClientId = "mvc"; options.ClientSecret = "secret"; options.ResponseType = "code id_token"; options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Add("api1"); options.Scope.Add("offline_access"); });

*** Configure ***
app.UseAuthentication();


Viewing all articles
Browse latest Browse all 9386

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>