unable to validate identity server token in dotntecore web - c#

I have a application which is like Microsoft default templates of Asp.netCoreWebApplication->ASP.netCoreWithReact.js.
In this react client will be wrapped inside a.netcore project. All of the UI pages will be served from React. .Net core backend will be used only for APIs.
Now I have implemented IdentityServer4 and able to generate token at this end point,
http://localhost:60739/token
From react client, on login button click I could make API call to http://localhost:60739/token and could generate token using granttype password flow. but i could not validate authroize my api end points with that token
below is my client definition with in identity server solution,
new Client
{
ClientName = "Resource Owner Flow",
ClientId = "resource_owner_flow",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("resource_owner_flow_secret".Sha256())
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.OfflineAccess
},
AllowOfflineAccess = true,
RefreshTokenUsage = TokenUsage.ReUse,
//AccessTokenLifetime = 60,
RefreshTokenExpiration = TokenExpiration.Absolute,
AbsoluteRefreshTokenLifetime = 300
}
below is piece of code i am using to refer identity server,
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:60739";
options.TokenValidationParameters.ValidateAudience = false;
options.TokenValidationParameters.ValidateIssuer = false;
options.TokenValidationParameters.ValidateIssuerSigningKey = false;
options.TokenValidationParameters.ValidateLifetime = false;
options.TokenValidationParameters.ValidateTokenReplay = false;
options.IncludeErrorDetails = true;
});
I could not successfully access protected api resources? Any idea ?
If i Call http://localhost:57102/api/Home/GetSomeProtectedData using token in header i get 500 internal server error. If i remove authorize attribute on protected resource it's working fine.
below is postman screenshot,
for token creation below is the log,
IdentityServer4.Validation.TokenRequestValidator: Information: Token request validation success,
{
"ClientId": "resource_owner",
"ClientName": "Resource Owner",
"GrantType": "password",
"Scopes": "openid",
"AuthorizationCode": "********",
"RefreshToken": "********",
"UserName": "superadmin#gmail.com",
"Raw": {
"username": "superadmin#gmail.com",
"password": "***REDACTED***",
"grant_type": "password",
"scope": "openid",
"response_type": "token"
}
}
but when I request protected API resource with token in header i get 500 internal server error and logs got created.

If you are getting 500 error, the problem is not the authorization flow. Else it would be 401.
You need to check out what is the real error. It can be a parsing error. You simpyly cannot finish the process because of an server side error. Please share more info, may be logs so I update the answer.

Related

IdentityServer 3 returns invalid_client when trying to authenticate with Blazor

I have an old IdentityServer 3 implementation and I'm trying not to change it to a newer version, I have been trying to authenticate a Blazor wasm application with it and so far almost everything went fine
Blazor Program.cs
...
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("Local", options.ProviderOptions);
});
Blazor appsettings.json
{
"Local": {
"Authority": "https://localhost:44343/",
"ClientId": "clientid",
"RedirectUri": "https://localhost:7170/authentication/login-callback",
"PostLogoutRedirectUri": "https://localhost:7170/authentication/logout-callback",
"ResponseType": "code"
}
}
just for testing purposes I added a new in memory client in my identityserver
IdentityServer 3 Clients
new Client {
ClientName = "client",
ClientId = "clientid",
Enabled = true,
AccessTokenType = AccessTokenType.Reference,
Flow = Flows.AuthorizationCodeWithProofKey,
RequireConsent = false,
ClientSecrets = new List < Secret > {
new Secret("secret".Sha256())
},
// where to redirect to after login
RedirectUris = {
"https://localhost:7170/authentication/login-callback",
"https://localhost:7170/connect/authorize/callback"
},
// where to redirect to after logout
PostLogoutRedirectUris = {
"https://localhost:7170/authentication/logout-callback"
},
AllowAccessToAllScopes = true,
AllowedScopes = new List < string > {
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles,
"Api"
}
}
I tried both with
Flow = Flows.AuthorizationCodeWithProofKey
and
Flow = Flows.AuthorizationCode
the problem is that when I try and login everything works fine until a /connect/token request is issued to which the server responds with invalid_client
I might have a clue on why this is happening but so far nothing I tried has done anything
as far as I know IdentityServer 3 requires the client secret and I didn't find a way around this so I tried to set it on the appsettings with:
"ClientSecret" : "secret"
but nothing changes

identityserver4 local login cause clients logout

User can login to identity server using local account. But this is cause of user sign out from MVC client that uses open id connect for external login and I don't know why exactly!
I checked IdentityServer4 connect/authorize endpoint for any sign out code but I can't find anything.
IdentityServer config:
new Client
{
ClientId = "mvc",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
AllowOfflineAccess = true,
RequireConsent = true,
// where to redirect to after login
RedirectUris = { "https://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
Client config:
builder.Services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddOpenIdConnect("oidc", "Demo IdentityServer4", options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
Aren't you by any chance using the same name for the cookies of your MVC client and your identity server?
As you are working in localhost for both MVC client and identity server, the cookie of single sign on could be overwriting the MVC cookie.
Have you checked this behavior with different domains?
And, what if you go back to the MVC Client and login from there, do you lose the single sign on? If I'm right, this time the MVC Cookie would be overwriting the identity server Cookie.
Did you check #IdentiyServer4 logs? I think those errors would help you to find the exact problem.

IdentityServer4 Reference Access Token Sometimes being transmitted as JWT Token instead

We have just upgraded our web app to .NET 5 and IdentityServer4 to V4, also we switched from hybrid flow to code + PKCE. The client is set to an access token type of reference, also the client uses bearer tokens for an internal API as well as cookies for the main website.
When we deploy to our internal development server (IIS 8.5) or to Azure App Services randomly when we ask for the access token (reference) we are returned an access token (JWT) instead. We did use the httpContext.GetTokenAsync() method but then replaced it with the identitymodel.aspnetcore GetUserAccessTokenAsync() method but it still returns a JWT Token.
I have validated the JWT tokens contents and they are the relevant user and their claims. I have also checked the persisted grant table and the reference token entered in there specifies it as a JWT instead of Reference.
The only way to rectify the situation is
Stop the website and identityserver
Clear the cookies in the browser
Delete all entries in the persisted grants table
Recycle the app pools
Start the identity server and then perform a login
Start the website which the login is for and suddenly we get a reference access token again
Identity Server Client Config
AllowedGrantTypes =
{
GrantType.AuthorizationCode,
"exchange_reference_token"
},
AccessTokenType = AccessTokenType.Reference,
AccessTokenLifetime = 86400,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
ClientSecrets =
{
new Secret("*******)
},
RedirectUris = { $"{client}/signin-oidc" },
PostLogoutRedirectUris = { $"{client}/signout-callback-oidc" },
FrontChannelLogoutUri = $"{client}/signout-oidc",
AllowedCorsOrigins = { client },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"API1",
"API2",
"API3",
"Signalr"
},
UpdateAccessTokenClaimsOnRefresh = true,
AllowOfflineAccess = true
I've found out what is causing the issue. We are using signalr in the website and we are having to use the exchange_reference_token, however in the exchange code it forces the access token to JWT, this then gets inserted in the persisted grant table causing any future request to return JWT instead of of reference access token
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var referenceToken = context.Request.Raw.Get("token");
if (referenceToken == null)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Missing Reference Token");
}
var result = await _validator.ValidateAccessTokenAsync(referenceToken);
if (result == null)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid Reference Token");
}
// Generate the JWT as if it was for the reference token's client
context.Request.Client.AccessTokenType = AccessTokenType.Jwt;
var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
context.Result = new GrantValidationResult(sub, GrantType, result.Claims);
}

Xamarin.forms authentication PKCE

I have an Identity server 4 application which i am trying to login to using my Xamarin.forms app using PKCE. I keep getting an error from the identity server one that i have actually not seen before. code_challenge is missing I am guessing that i am using the wrong grant type but all the documentation i have found for Xamarin says i should be using this one.
How do you connect Xamarin to Identity server 4?
The error
fail: IdentityServer4.Validation.AuthorizeRequestValidator[0]
code_challenge is missing
{
"ClientId": "xamarin",
"ClientName": "eShop Xamarin OpenId Client",
"RedirectUri": "1046123799103-h63f9o1cnj78fo26okng1aacr9e89u2e:/oauth2redirect",
"AllowedRedirectUris": [
"http://localhost:5001/signin-oidc"
],
"SubjectId": "anonymous",
"ResponseType": "code",
"ResponseMode": "query",
"GrantType": "authorization_code",
"RequestedScopes": "",
"State": "egfczresvcjyeerw",
"Raw": {
"client_id": "xamarin",
"redirect_uri": "1046123799103-h63f9o1cnj78fo26okng1aacr9e89u2e:/oauth2redirect",
"scope": "profile openid nol_api navinfo",
"response_type": "code",
"state": "egfczresvcjyeerw"
}
}
Client id in Identity server
new Client
{
ClientId = "xamarin",
ClientName = "eShop Xamarin OpenId Client",
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { "http://localhost:5001/signin-oidc" },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { "http://localhost:8008/Account/Redirecting" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"navinfo",
$"{nolConfig.Client}_api"
},
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
RequireClientSecret = false
}
xamarin code
Authenticator = new OAuth2Authenticator
(
_clientId,
_secret,
_scopes,
new Uri(_discoveryDoc.AuthorizationEndpoint),
_redirectUri,
new Uri(_discoveryDoc.TokenEndpoint),
null,
isUsingNativeUI: true
);
If I remove RequirePkce = true, from the client in the identity server I no longer get the error in question. From what I have been able to find it would seam that Xamarin.auth doesn't support PKCE yet. Which means i will either have to disable it or implement it myself.
How do Login to Identity server 4 from XAmarin forms with PKCE enabled.
It looks like PKCE is enabled in OAuth2Authenticator by not having a client secret:
protected bool IsProofKeyCodeForExchange
{
get
{
return
accessTokenUrl != null // AccessToken url is defined
&&
string.IsNullOrWhiteSpace(clientSecret) // Client Secret is not defined
;
}
}
So I would try
Authenticator = new OAuth2Authenticator
(
_clientId,
null,
_scopes,
new Uri(_discoveryDoc.AuthorizationEndpoint),
_redirectUri,
new Uri(_discoveryDoc.TokenEndpoint),
null,
isUsingNativeUI: true
);

Identityserver4 not sending access_token

I'm trying to create react spa with authentication. I'm using identityserver4 for OIDC provider. Whenever I login, I am redirected to login page and after providing credentials, I'm redirected to SPA, but UserManger does not have access_token.
I've tried to play with Client on server side, but none of that worked.
For Frontend I'm using this example https://github.com/Franpastoragusti/oidc-react-app , but converted to typescript
And backend is slightly modified Identityserver quickstart.
This is my Client in Config.cs
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "primrose.web",
ClientName = "Primrose Web Application",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
AccessTokenType = AccessTokenType.Jwt,
RequireConsent = false,
AccessTokenLifetime = 120,
AlwaysIncludeUserClaimsInIdToken = true,
RedirectUris = {
"http://localhost:3000/callback",
"http://localhost:3000/silentRenew",
},
PostLogoutRedirectUris =
{
"http://localhost:5000/account/login"
},
AllowedCorsOrigins = { "http://localhost:3000" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"primrose.web"
},
}
};
}
This is my oidc configuration in client app:
export const IDENTITY_CONFIG: any = {
authority: "http://localhost:5000", //(string): The URL of the OIDC provider.
client_id: "primrose.web", //(string): Your client application's identifier as registered with the OIDC provider.
redirect_uri: "http://localhost:3000/callback", //The URI of your client application to receive a response from the OIDC provider.
login: "http://localhost:5000/account/login",
automaticSilentRenew: false, //(boolean, default: false): Flag to indicate if there should be an automatic attempt to renew the access token prior to its expiration.
loadUserInfo: true, //(boolean, default: true): Flag to control if additional identity data is loaded from the user info endpoint in order to populate the user's profile.
silent_redirect_uri: "http://localhost:3000/silentRenew", //(string): The URL for the page containing the code handling the silent renew.
post_logout_redirect_uri: "http://localhost:5000/account/login", // (string): The OIDC post-logout redirect URI.
audience: "primrose.web", //is there a way to specific the audience when making the jwt
responseType: "id_token token", //(string, default: 'id_token'): The type of response desired from the OIDC provider.
grantType: "password",
scope: "openid profile primrose.web", //(string, default: 'openid'): The scope being requested from the OIDC provider.
webAuthResponseType: "id_token token"
};
export const METADATA_OIDC: any = {
issuer: "http://localhost:5000",
jwks_uri: "http://localhost:5000/.well-known/openid-configuration/jwks",
authorization_endpoint: "http://localhost:5000/connect/authorize",
token_endpoint: "http://localhost:5000/connect/token",
userinfo_endpoint: "http://localhost:5000/connect/userinfo",
end_session_endpoint: "http://localhost:5000/connect/endsession",
check_session_iframe: "http://localhost:5000/connect/checksession",
revocation_endpoint: "http://localhost:5000/connect/revocation",
introspection_endpoint: "http://localhost:5000/connect/introspect"
};
this is what usermanager returns when addUserLoaded event is fired
access_token: undefined
expires_at: undefined
id_token: "eyJhbGciOiJSU...(I deleted rest of the token)"
profile:
amr: ["pwd"]
auth_time: 1564597858
email: "pipa#papa.pl"
idp: "local"
name: "pipa#papa.pl"
preferred_username: "pipa#papa.pl"
sid: "2044d39c30e316722516f6d376e24838"
sub: "c0ca848c-8d2d-48e6-829f-e1d29838ecef"
__proto__: Object
refresh_token: undefined
scope: "openid profile primrose.web"
session_state: "kmFYyCDxsql8D4-WD7J07OwW4zhMDdqLjDkHriNuwqg.852977a2a19ba24a7bb5a12d389bebfd"
state: undefined
token_type: undefined
expired: (...)
expires_in: (...)
scopes: (...)
__proto__: Object
I want to retrieve this access token from OIDC provider in my client app, but it comes undefined

Categories