Identity Server 4 Consent Screen Never Shows - authentication

I'm trying to get the Consent Screen to show from the Identity Server 4 Samples,
I've configured the client so it requires consent like so:
new Client
{
ClientId = "openIdConnectClient",
ClientName = "Example Implicit Client Application",
AllowedGrantTypes = GrantTypes.Implicit,
RequireConsent = true,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"customAPI"
},
RedirectUris = new List<string> {"https://localhost:44330/signin-oidc"},
PostLogoutRedirectUris = new List<string> { "https://localhost:44330" }
}
The project contains controllers and views for the Consent Screen However I cannot get it to load. If needed I can show the classes or views for the Consent.
Does anyone know how to configure IdentityServer4 to Display the Consent Screen?

You can force the consent screen to always be shown in your client by setting the Prompt property when you register the OpenIDConnect scheme:
.AddOpenIdConnect(options =>
{
options.Authority = "https://localhost:6001";
options.ClientId = "xxx";
options.ClientSecret = "xxxx";
options.ResponseType = "code";
...
options.Prompt = "consent";
});

Maybe Identity Server is remembering your previous consent. Just add this to the client options (the default value is true):
AllowRememberConsent = false,

Related

Identity Server - Authorization code flow issue - Login page

The issue I am facing is after successful login from my MVC app to ID Server, I am not getting redirected to the applications secure page. instead, the identity server login page reappears.
I created the ID server using hte following template.
dotnet new is4inmem -n IdentityServerSample
My ID Server runs in port 5000 (http only)
I have another MVC application, which runs in port 5006 (http only).
my client settings and scope settings in ID Server config file is as below..
..., new Client
{
ClientId = "AuthCode_Flow_Client",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { "http://localhost:5006/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:5006/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:5006/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "ValuesAPI_ReadOnly" }
},...
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("scope1"),
new ApiScope("scope2"),
new ApiScope("ValuesAPI_ReadOnly"),
};
The configure serivice method in my MVC is as below.
services.AddAuthentication(opts =>
{
opts.DefaultScheme = "Cookies";
opts.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", opts =>
{
opts.Authority = "http://localhost:5000";
opts.RequireHttpsMetadata = false;
opts.ClientId = "AuthCode_Flow_Client";
opts.ClientSecret = "secret";
opts.SaveTokens = true;
opts.ResponseType = "code";
});
In my pipeline, I have added the UseAuthentication and UseAuthorization() middlewares.
ISSUE
When I hit a secure page in my MVC application, I get redirected to ID SErver login page. After giving valid credentials (bob / bob), I dont see any errors in id server console log but still I am getting redirected ot login page itself.
Any suggestions.

IdentityServer4 ADFS External Not Returning Roles

I have created an IdentityServer4 IDP using the standard template for Core Identity. I am looking to have an External provider being out ADFS 2016 Server. I have added this to the AddAuthentication() in Startup.cs
services.AddAuthentication()
.AddOpenIdConnect("adfs", "ADFS", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "[AuthURL]";
options.ClientId = "[ClientId]";
options.ResponseType = "id_token token code";
options.Scope.Add("profile");
options.Scope.Add("email");
options.CallbackPath = "/signin-adfs";
options.SignedOutCallbackPath = "/signout-callback-adfs";
options.RemoteSignOutPath = "/signout-adfs";
options.ClaimActions.Add(new JsonKeyClaimAction("role", null, "role"));
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
It successfully redirects to the ADFS login window. Once signed in it calls the ExternalController.cs CallBack() correctly and I do have a successful authentication.
public async Task<IActionResult> Callback()
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
The issue I am having is that I am not getting back the full user. I see claims but I do not see roles. I am used to seeing a JWT token which includes a list of Roles, however, I do not see these roles within the Result from above.
How can I either get a JWT token back from the Authentication against ADFS or have the roles returned and be within the Result?
Inside OIDC add scope for roles:
options.Scope.Add("roles");
Inside config.cs in IDS4 make sure your client has the allowed scopes:
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"roles",
},
If it's an API, make sure config.cs has the correct userclaims:
new ApiResource()
{
Name = "API",
DisplayName = "display",
ApiSecrets =
{
new Secret("secret".Sha256()),
new Secret
{
Value = "4A04D56554F731CCD123BB574D6918C8C83BDF65",
Type = "X509Thumbprint",
Description = "Certificate"
}
},
Scopes = new List<string>(){"postman Web API"},
Enabled = true,
UserClaims =
{
JwtClaimTypes.Name,
JwtClaimTypes.Email,
JwtClaimTypes.Subject,
JwtClaimTypes.Role,
JwtClaimTypes.Address,
JwtClaimTypes.Confirmation,
JwtClaimTypes.EmailVerified,
JwtClaimTypes.Id,
JwtClaimTypes.Profile
}
},

nopCommerce Authentication using Identity Server4 Implementation Issue

I am using NopCommerce 4.40.3 and Identity Server 4. I am trying to integrate Identity Server authentication with NopCommerce. I have followed the existing ExternalAuth.Facebook project approach and created the plugin. I am able to install and configure the plugin successfully. I am able to show the "Identity Server Authentication" button and when I click it is redirecting to Identity Server Login Page and I am able to authenticate to Identity Server with out any issues. I can able to see the claims and I can see the success message in the identity server console. But NopCommerce site still shows not logged in and when I try to access different pages in NopCommerce, It is redirecting me to login page.
After login, I am able to see the Identity Server cookies like "idsrv" and "idsrv.session". When I logout from Identity Server, I can see both cookies are cleared out.
My question is, how can I set successful login to NopCommerce site. Here's my implementation code. I don't know what I have missed in the configuration or in the implementation. Please help me.
Identity Server Client Configuration:
new Client
{
ClientName = "MiniApple.App.NopCommerce",
ClientId = "MiniApple.App.NopCommerce",
AllowedGrantTypes =GrantTypes.HybridAndClientCredentials,
RedirectUris = new List<string>{ "https://localhost:44369/signin-oidc" }, //Client Application Address
RequirePkce = false,
RequireConsent = true,
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
IdentityServerConstants.StandardScopes.Email,
"MiniApple.API.Employee",
"roles"},
ClientSecrets = { new Secret("abcdefghijklmnopqrstuvwxyz".Sha512()) },
AllowAccessTokensViaBrowser = true,
AlwaysSendClientClaims = true,
PostLogoutRedirectUris = new List<string> { "https://localhost:44369/signout-callback-oidc" }
},
NopCommerce Authentication Registration:
public class IdentityServerAuthenticationRegistrar : IExternalAuthenticationRegistrar
{
/// <summary>
/// Configure
/// </summary>
/// <param name="builder">Authentication builder</param>
public void Configure(AuthenticationBuilder builder)
{
builder.AddOpenIdConnect("oidc", options => {
var settings = EngineContext.Current.Resolve<IdentityServerExternalAuthSettings>();
options.SignInScheme = "Cookies";
options.Authority = settings.Authority;
options.ClientId = settings.ClientKeyIdentifier;
options.ResponseType = settings.ResponseType;
options.SaveTokens = true;
options.ClientSecret = settings.ClientSecret;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add(settings.Scope);
options.Scope.Add("roles");
options.ClaimActions.MapUniqueJsonKey("role", "role");
options.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "role"
};
});
}
}
Identity Server Console Output:
info: IdentityServer4.Validation.TokenRequestValidator[0]
Token request validation success, {
"ClientId": "MiniApple.App.NopCommerce",
"ClientName": "MiniApple.App.NopCommerce",
"GrantType": "authorization_code",
"AuthorizationCode": "****F988",
"RefreshToken": "********",
"Raw": {
"client_id": "MiniApple.App.NopCommerce",
"client_secret": "***REDACTED***",
"code": "18978F1D183EDFA3E3F5918B85F43DDFEAFE74D49E207E2449F59A9490BFF988",
"grant_type": "authorization_code",
"redirect_uri": "https://localhost:44369/signin-oidc"
}
}
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.UserInfoEndpoint for /connect/userinfo
info: IdentityServer4.ResponseHandling.UserInfoResponseGenerator[0]
Profile service returned the following claim types: given_name family_name role
After successful login with identity server, it is redirecting to https://localhost:44369/signin-oidc and I am getting 404 error.
The issue is similar to the below
[question]: https://www.nopcommerce.com/en/boards/topic/60547/problems-making-custom-externalauth-plugin-for-openidconnect-to-auth0
Once I have changed the code as below, the authentication is works fine.
public void Configure(AuthenticationBuilder builder)
{
builder.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => {
//Set Open Id Parameters
var settings = EngineContext.Current.Resolve<IdentityServerExternalAuthSettings>();
options.Authority = settings.Authority;
options.ClientId = settings.ClientId;
options.ClientSecret = settings.ClientSecret;
options.ResponseType = settings.ResponseType;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add(settings.Scope);
options.Scope.Add("roles");
options.Scope.Add("openid");
options.Scope.Add("profile");
//options.Scope.Add("email");
options.SaveTokens = true;
options.ClaimActions.MapUniqueJsonKey("role", "role");
options.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "role"
};
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = context =>
{
context.HandleResponse();
var errorUrl = context.Properties.GetString(IdentityServerAuthenticationDefaults.ErrorCallback);
context.Response.Redirect(errorUrl);
return Task.FromResult(0);
}
};
});
}

identityserver4 Hybrid follow without competed login

I have an API that needs to secure allowing 3rd party asp.net core MVC web application to request an access token and use this access token to request the secured API.
i created HybridAndClientCredentials client on the identity server
ClientId = "testclient",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AllowOfflineAccess = true,
// secret for authentication
ClientSecrets =
{
new Secret("password".Sha256())
},
RedirectUris = {"http://127.0.0.1:55950",
"http://localhost/testLogin",
"https://localhost:44322/",
"https://localhost:44302/",
"https://localhost:44303/signin-oidc"},
RequireConsent = false,
// scopes that client has access to
AllowedScopes = { "roles" , IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile}
and MVC client as showing in identity server 4 documentation
.AddOpenIdConnect("oidc", options =>
{
options.Authority = Constants.Authority;
options.RequireHttpsMetadata = false;
options.ClientSecret = "password";
options.ClientId = "testclient";
options.ResponseType = "code id_token";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
//options.Scope.Add("email");
//options.Scope.Add("resource1.scope1");
options.Scope.Add("offline_access");
options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
});
it's working but the user appears to be logged in the MVC application all I want is the access token to be used in calling the secured API also I don't want to use [authorize] attribute on the MVC client to redirect the user to identity server login page.
Something in the MVC application must to trigger a challenge to the OpenIDconnect handler, that starts the process to authenticate the user. As a result the user is logged in and you get access to the tokens.
Using a [Authorize] attribute is one way to trigger a challenge, or to do it manually using code like:
public async Task Login()
{
await HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties() { RedirectUri = "/" });
}

identity server 4, Asp.net identity and

I am trying to integrate identity server 4 with asp.net identity, the documentation is very good https://identityserver4.readthedocs.io/en/latest/quickstarts/6_aspnet_identity.html
But I would like to be able to make the connection without going through the login page, but to make a direct access via a simple GET while passing the parameters.
I found this article: https://damienbod.com/2017/04/14/asp-net-core-identityserver4-resource-owner-password-flow-with-custom-userrepository/
with this method
var response = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = _disco.TokenEndpoint,
ClientId = "resourceownerclient",
ClientSecret = "dataEventRecordsSecret",
Scope = "email openid dataEventRecords offline_access",
UserName = user,
Password = password
});
But can't make it work with Postman
I have an "invalid_request" error
Here is the client's statement:
new Client
{
ClientId = "resourceownerclient",
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AccessTokenType = AccessTokenType.Jwt,
AccessTokenLifetime = 3600,
IdentityTokenLifetime = 3600,
UpdateAccessTokenClaimsOnRefresh = true,
SlidingRefreshTokenLifetime = 30,
AllowOfflineAccess = true,
RefreshTokenExpiration = TokenExpiration.Absolute,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
AlwaysSendClientClaims = true,
Enabled = true,
ClientSecrets= new List<Secret> { new Secret("dataEventRecordsSecret".Sha256()) },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"dataEventRecords"
},
AllowAccessTokensViaBrowser=true
}
What is the recommended way to be able to use Asp.net Identity in this way?
You are missing grant_type in your postman request:
POST /connect/token
client_id=resourceownerclient&
client_secret=dataEventRecordsSecret&
grant_type=password&
username=damienbod&
password=damienbod&
scope=email%20openid%20dataEventRecords%20offline_access
Not sure if this is the only issue you have but it definitely one of them. The identityserver logs will contain more details of what is wrong with the request if this is not the only problem.