Author : HASSAN MD TAREQ | Updated : 2020/06/19

Configurations

  • Config.cs
  • Quickstart/AccountOptions.cs

Config

  • Ids: Identity Resources list i.e. OpenId, Profile, Address etc. (related to identity user info)
  • Apis: ApiResources
  • Clients: List of clients that will use (allowed to use) Identity Server
public static class Config
{
	public static IEnumerable<IdentityResource> Ids =>
		new IdentityResource[]
		{
			new IdentityResources.OpenId(),
			new IdentityResources.Profile(),
			//new IdentityResources.Address()
		};


	public static IEnumerable<ApiResource> Apis =>
		new ApiResource[]
		{
			new ApiResource("api1", "My API #1")
		};


	public static IEnumerable<Client> Clients =>
		new Client[]
		{
			// client credentials flow client
			new Client
			{
				ClientId = "client",
				ClientName = "Client Credentials Client",

				AllowedGrantTypes = GrantTypes.ClientCredentials,
				ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

				AllowedScopes = { "api1" }
			},

			// MVC client using code flow + pkce
			new Client
			{
				ClientId = "mvc",
				ClientName = "MVC Client",

				AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
				RequirePkce = true,
				ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },

				RedirectUris = { "http://localhost:5003/signin-oidc" },
				FrontChannelLogoutUri = "http://localhost:5003/signout-oidc",
				PostLogoutRedirectUris = { "http://localhost:5003/signout-callback-oidc" },

				AllowOfflineAccess = true,
				AllowedScopes = { "openid", "profile", "api1" }
			},

		  new Client
			{
				ClientId = "postman",
				ClientName = "Postman Client",

				AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
				RequirePkce = false,
				ClientSecrets = { new Secret("hovermind.postman".Sha256()) },

				RedirectUris = { "http://localhost:5003/signin-oidc" },
				FrontChannelLogoutUri = "http://localhost:5003/signout-oidc",
				PostLogoutRedirectUris = { "http://localhost:5003/signout-callback-oidc" },

				AllowOfflineAccess = true,
				AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile }
			},

			// SPA client using code flow + pkce
			new Client
			{
				ClientId = "spa",
				ClientName = "SPA Client",
				ClientUri = "http://identityserver.io",

				AllowedGrantTypes = GrantTypes.Code,
				RequirePkce = true,
				RequireClientSecret = false,

				RedirectUris =
				{
					"http://localhost:5002/index.html",
					"http://localhost:5002/callback.html",
					"http://localhost:5002/silent.html",
					"http://localhost:5002/popup.html",
				},

				PostLogoutRedirectUris = { "http://localhost:5002/index.html" },
				AllowedCorsOrigins = { "http://localhost:5002" },

				AllowedScopes = { "openid", "profile", "api1" }
			}
		};
}

AccountOptions

Account related options i.e. AutomaticRedirectAfterSignOut, AllowRememberLogin etc.

public class AccountOptions
{
	public static bool AllowLocalLogin = true;
	public static bool AllowRememberLogin = true;
	public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);

	public static bool ShowLogoutPrompt = true;
	public static bool AutomaticRedirectAfterSignOut = false; // apter logout, user will be signed out of IDP also and redirect to main app

	// specify the Windows authentication scheme being used
	public static readonly string WindowsAuthenticationSchemeName = Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme;
	// if user uses windows auth, should we load the groups from windows
	public static bool IncludeWindowsGroups = false;

	public static string InvalidCredentialsErrorMessage = "Invalid username or password";
}

Claims in Access Token

Add Identity Resources

public static class Config
{
	public static IEnumerable<IdentityResource> Ids =>
		new IdentityResource[]
		{
			new IdentityResources.OpenId(),
			new IdentityResources.Profile(),
			new IdentityResources.Address()
			
			new IdentityResources {"a", "This is A"}
			new IdentityResources {"b", "This is B"}
			new IdentityResources {"c", "This is C"}
			new IdentityResources {"d", "This is D"}
		};


	   // 
}

Allow Client to use (all or subset of) those Identity Resources

public static class Config
{
	public static IEnumerable<IdentityResource> Ids =>
		new IdentityResource[]
		{
			new IdentityResources.OpenId(),
			new IdentityResources.Profile(),
			new IdentityResources.Address()
			
			new IdentityResources {"a", "This is A"}
			new IdentityResources {"b", "This is B"}
			new IdentityResources {"c", "This is C"}
			new IdentityResources {"d", "This is D"}
		};


	// ... ... ...


	public static IEnumerable<Client> Clients =>
	
		new Client[]
		{
		  // ... ... ...


		  new Client
			{
				ClientId = "postman",
				ClientName = "Postman Client",

				AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
				RequirePkce = false,
				ClientSecrets = { new Secret("hovermind.postman".Sha256()) },

				RedirectUris = { "http://localhost:5003/signin-oidc" },
				FrontChannelLogoutUri = "http://localhost:5003/signout-oidc",
				PostLogoutRedirectUris = { "http://localhost:5003/signout-callback-oidc" },

				AllowOfflineAccess = true,
				AllowedScopes = { 
					IdentityServerConstants.StandardScopes.OpenId, 
					IdentityServerConstants.StandardScopes.Profile
					"a",
					"b",
					"c",
				}
			},

			// ... ... ...
}

Client (WebApp) is asking for (all or subset of) allowed resources (info. about user) from IDP

public class Startup
{
	// ... ... ...
	
	public void ConfigureServices(IServiceCollection services)
	{
		// ... ... ...            

		services.AddAuthentication(options =>
		{
			options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
			options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
		})
		.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
		.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
		{
			options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
			options.Authority = "https://localhost:5001/";
			options.ClientId = "...";
			options.ResponseType = "code";
			options.UsePkce = true;              
			options.SaveTokens = true;
			options.ClientSecret = "...";
			options.GetClaimsFromUserInfoEndpoint = true;
			
			// claims that (WebApp) client asking from IDP
			options.Scope.Add("openid");
			options.Scope.Add("profile");
			options.Scope.Add("a");
			options.Scope.Add("b");
		});


	}
}

So,

  • DP Config => IDP added 4 Identity Resources => a, b, c, d (& openid, profile)
  • IDP Config => Client was allowed for 3 Identity Resources => a, b, c (& openid, profile)
  • (WebApp) Client => asked for 2 claims (Identity Resources) => a, b (& openid, profile)

Therefore, Access Token returned form IDP => will contain Claim ‘a’ & Claim ‘b’ (+ claim openid, + claim profile)