I have been tried to apply several kind of setting on Startup.cs as shown ob the given link:
https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html
But unfortunately I cannot set the base url for Authority parameter when I check on the following url:
https://my-pc-id:8085/_configuration/MyApp.WebUI
It seems to be weird, because if we cannot set this parameter, why there is such an option on this config?
using System.IdentityModel.Tokens.Jwt;
// ...
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "my-pc-id:8085";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
});
Change the Authority property like so:
// base-address of your identityserver
.Authority = "https://my-pc-id:8085/_configuration/MyApp.WebUI";
Related
I have a blazor app with azure ad auth, where human users are redirected to the microsoft log in screen etc, I now have a requirement that a tool needs to be able to access specific pages using a key in the header.
Is this possible? If so how do I add the second type of authorization where it effectively ignores the first type if the key is present?
I use the following code :
Connection Database
get conncentionString from appsettings.json :
var connectionString = builder.Configuration.GetConnectionString("AppContext") ?? throw new InvalidOperationException("Connection string 'AppContext' not found.");
Add DbContext :
builder.Services.AddDbContext<AppContext>(options =>
{
options.UseLazyLoadingProxies().UseSqlServer(connectionString, x => x.UseNetTopologySuite());
});
Add Identity
builder.Services.AddIdentity<IdentityUser, IdentityRole>(option => {
option.Password.RequireDigit = true;
option.Password.RequiredUniqueChars = 5;
option.Password.RequireLowercase = false;
option.Password.RequireNonAlphanumeric = false;
option.Password.RequireUppercase = false;
option.Password.RequiredLength = 16;
}).AddEntityFrameworkStores<AppContext>();
Add Authentication API JWT
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://Example.com",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("keyhash"))
};
});
Add Authentication Web Cookie
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options => {
options.LoginPath = "/Login";
options.LogoutPath = "/Logout";
options.AccessDeniedPath = "/AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromMinutes(100000);
});
Used packages
1. Microsoft.EntityFrameworkCore.Design Version="6.0.5"
2. Microsoft.EntityFrameworkCore.Proxies Version="6.0.5"
3. Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite Version="6.0.5"
I've got the following client set up in IdentityServer:
internal class Clients
{
public static IEnumerable<Client> Get()
{
return new List<Client>
{
new Client
{
ClientId = "Client",
ClientName = "Client",
ClientSecrets = new List<Secret> {new Secret("blablabla".Sha256())},
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { Startup.Configuration.GetValue<string>("Clients", "https://localhost:5002") + "/signin-oidc" },
PostLogoutRedirectUris = { Startup.Configuration.GetValue<string>("Clients", "https://localhost:5002") + "/signout-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"Business-to-Business-users",
"reporting-urls"
},
RequirePkce = true,
AllowPlainTextPkce = false,
AllowAccessTokensViaBrowser = true
}
};
}
}
I'm trying to modify the mvc client to login to the above identity server. In startup.cs I modified cllientID, ClientSecret and Authority to match the client settings. This is my ConfigureServices():
services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie("cookie")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = Configuration.GetValue<string>("IdentityHost", "https://localhost:5000");
options.ClientId = "Client";
options.ClientSecret = "blablabla";
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.ResponseType = "code";
options.UsePkce = true;
options.ResponseMode = "query";
options.Scope.Add("roles");
options.Scope.Add("Business-to-Business-users");
options.Scope.Add("reporting-urls");
options.RequireHttpsMetadata = false;
options.ClaimActions.MapUniqueJsonKey("role", "role");
options.ClaimActions.MapUniqueJsonKey("Business-to-Business-user", "Business-to-Business-user");
options.ClaimActions.MapUniqueJsonKey("reporting-url", "reporting-url");
options.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "role",
};
});
first I got a bug that he needs https but instead uses http. So I added the following code to my Configure:
app.Use((context, next) => {
context.Request.Scheme = "https";
return next();
});
Now that this error was solved, I ran into a different one.
As soon as I'm trying to login to my client, I got the following error in my browser (Opera): "ERR_TOO_MANY_REDIRECTS".
Does anyone have an idea how I can proceed? Both Identity and the client are seperate docker containers.
I have an ASP.NET Core 2.2 application with the following configuration:
And this is my Startup.cs class
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = $"{ Configuration.GetValue<string>("AzureAdB2C:Instance") }/{ Configuration.GetValue<string>("AzureAdB2C:Tenant") }/{ Configuration.GetValue<string>("AzureAdB2C:SignUpSignInPolicyId") }/v2.0";
options.ClientId = Configuration.GetValue<string>("AzureAdB2C:ClientId");
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.ClientSecret = Configuration.GetValue<string>("AzureAdB2C:ClientSecret");
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
When I run this the B2C login page pops-up, however once I enter the credentials I get the error below. URL is redirected to https://localhost:xxxx/signin-oidc
How can I solve this problem?
This is the similar issue, the same error occurred when external login is canceled and redirects to the source application. You could use OnRemoteFailure to handle the exception.
AddOpenIdConnect("oidc", options => {
// ...
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = ctx =>
{
ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message));
ctx.HandleResponse();
return Task.FromResult(0);
}
};
});
I am trying to configure my Jwt Bearer issuer key but, in production usually, I use Azure Key Vault wrapped by a KeyManager.
The KeyManager class is configured in Dependency Injection but, in ConfigureServices method I cannot use that (obviously), but if I cannot use that I cannot retrieve my key.
My solution at the moment is to build a temporary service provider and use it, but I think is not the state of the art (and I need to create two copies of singletons, not the best).
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
ServiceProvider sp = services.BuildServiceProvider();
IKeyManager keyManager = sp.GetService<KeyManager>();
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = keyManager.GetSecurityKeyFromName("jwt").Result,
ValidIssuer = "https://api.example.com",
ValidateIssuer = true
};
options.Audience = "https://api.example.com";
options.Authority = "https://api.example.com";
options.SaveToken = true;
});
Use Options pattern and implement IConfigureNamedOptions<JwtBearerOptions>:
public class ConfigureJwtBearerOptions : IConfigureNamedOptions<JwtBearerOptions>
{
private readonly IKeyManager _keyManager;
public ConfigureJwtBearerOptions(IKeyManager keyManager)
{
_keyManager = keyManager;
}
public void Configure(JwtBearerOptions options)
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = _keyManager.GetSecurityKeyFromName("jwt").Result,
ValidIssuer = "https://api.example.com",
ValidateIssuer = true
};
options.Audience = "https://api.example.com";
options.Authority = "https://api.example.com";
options.SaveToken = true;
}
public void Configure(string name, JwtBearerOptions options)
{
Configure(options);
}
}
In Startup.cs:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer();
services.ConfigureOptions<ConfigureJwtBearerOptions>();
So, after more researches, I found this page on Microsoft's docs: Use DI services to configure options (refer also to that answer that refers to handling dynamically multiple Jwt Issuers).
services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
.Configure<IKeyManager>((options, keyManager) => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = keyManager.GetSecurityKeyFromName("jwt").Result,
ValidIssuer = "https://api.example.com",
ValidateIssuer = true
};
options.Audience = "https://api.example.com";
options.Authority = "https://api.example.com";
options.SaveToken = true;
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer();
I have been getting this error and i have searched for answer online and almost all of them has been talking about requesturis and i have double checked to make sure that my uris are configured properly. I did not find any clue about it. Any thoughts.
Identity Server 4 settings:-
public static IEnumerable<Client> GetClients()
{
return new List<Client>()
{
new Client
{
ClientName="KtsWeb App",
ClientId="ktswebclient",
AllowedGrantTypes= GrantTypes.Hybrid,
AccessTokenType = AccessTokenType.Reference,
RedirectUris = new List<string>()
{
"https://localhost:44355/signin-oidc" //Client URL Address
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}
Client settings:-
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
}).AddCookie("Cookies",
(options) =>
{
options.AccessDeniedPath = "/Authorization/AccessDenied";
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://localhost:44380"; //Identity Server URL Address
options.ClientId = "ktswebclient";
options.ResponseType = "code id_token";
options.Scope.Add("openid");
options.Scope.Add("profile");
options.SaveTokens = true;
});
You should always check the identity server logs it would have given you a clear error message probably unsupported grant type.
You have created a hybrid client but forgot to add the secret.
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
}
};
Your code isnt supplying the secret
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");
options.ClaimActions.MapJsonKey("website", "website");
});