Invalid Grant error after being redirected to client application from OpenIdDict application - asp.net-core

I have an application using OpenIdDict Beta 6 with ASP.NET Core 5.
I am using OpenIdDict Velusia sample and I have the following client:
OpenIddictApplicationDescriptor application = new OpenIddictApplicationDescriptor {
ClientId = "spa",
ClientSecret = "secret",
ConsentType = OpenIddictConstants.ConsentTypes.Implicit,
PostLogoutRedirectUris = {
new Uri("https://localhost:5002/oidc/signout")
},
RedirectUris = {
new Uri("https://localhost:5002/oidc/signin"),
},
Permissions = {
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Prefixes.Scope + "api"
},
Requirements = {
OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange
}
};
On my client application I am using OIDC Client and I have the following settings:
const settings: UserManagerSettings = {
automaticSilentRenew: true,
authority: "https://localhost:5000",
client_id: 'spa',
client_secret: "secret",
filterProtocolClaims: true,
loadUserInfo: true,
post_logout_redirect_uri: "https://localhost:5000/oidc/signout",
redirect_uri: "https://localhost:5000/oidc/signin",
response_mode: 'query',
response_type: 'code',
scope: 'openid profile email api'
};
I am able to login with email/password and to logout ...
When I login with Google I am redirected back to OpenIdDict application.
I get the successful login message and asked to confirm email to create the account.
I confirm it and I get redirected back to the spa client application ...
But when the OIDCClient-JS, in the spa, calls "/connect/token" I get the error:
Error: invalid_grant
It was working with previous OpenIdDict version ...
What am I missing?

Related

Microsoft Azure login success returns empty scopes - react-native-app-auth - Getting 401

While I try to make an custome backend API call with the accessToken I receive from login success using react-native-app-auth, the call fails and returns a 401 error.
My login succeeds with no error but the response I get after login, consists of empty scopes scopes: []
Below is my config,
const AuthorizationConfig = {
appId: 'XXXXX',
tenantId: 'XXXX',
appScopes: [
'openid',
'offline_access',
'profile',
'User.Read',
'api://XXXX/access_as_user',
],
};
export const config: any = {
warmAndPrefetchChrome: true,
clientId: AuthorizationConfig.appId,
redirectUrl: 'com.dcomobile://react-native-auth/',
scopes: AuthorizationConfig.appScopes,
additionalParameters: {prompt: 'select_account'},
serviceConfiguration: {
authorizationEndpoint:
'https://login.microsoftonline.com/' +
AuthorizationConfig.tenantId +
'/oauth2/v2.0/authorize',
tokenEndpoint:
'https://login.microsoftonline.com/' +
AuthorizationConfig.tenantId +
'/oauth2/v2.0/token',
},
};
I call this function to authorize which in turn opens a Microsoft Login window in a mobile browser
const result = await authorize(config);
result.accessToken contains the token which I have to append to the header section in my API call. The token is a Bearer token
I'm wondering if my scopes are wrong as it as scopes for both MSGraph and custom API.
Any leads would be helpful! TIA

Identity Server 4 External Provider Claims Extension

I've identity server 4 configurations in an ASP.NET Core app. Along with opened and profile scope I also want to get the birthday of the logged-in user as claims. I'm having no luck with the following configuration
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.AppId = "XXX";
options.AppSecret = "XXX";
options.SaveTokens = true;
options.Scope.Add("user_birthday");
options.Fields.Add("birthday");
})
Any idea why this is not working?
OIDC client request configuration
var config = {
authority: "https://localhost:44330",
client_id: "ff-client",
redirect_uri: "https://localhost:5003/callback.html",
response_type: "id_token token",
scope:"openid profile gateway identity",
post_logout_redirect_uri: "https://localhost:5003/index.html",
acr_values: "idp:Facebook",
loadUserInfo: true,
};
Check if user granted access. ref: https://developers.facebook.com/docs/graph-api/using-graph-api/common-scenarios/#how-to-get-an-access-token
If you want to confirm that the User has granted your app the user_birthday permission, you can perform a GET operation on the /{user-id}/permissions edge. Assuming the User granted the permission, the API response would look like this:
Sample Response
{
"data": [
{
"permission":"user_birthday",
"status":"granted"
}
]
}

The 'offline_access' scope is not allowed when using OpenIdDict

Using Asp.Net Core 5.0 with Identity and OpenIdDict I have the following:
services.AddOpenIddict()
.AddCore(x => {
x.UseEntityFrameworkCore().UseDbContext<Context>().ReplaceDefaultEntities<Application, Authorization, Scope, Token, Int32>();
})
.AddServer(x => {
x.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token")
.SetUserinfoEndpointUris("/connect/userinfo");
x.RegisterScopes(OpenIddictConstants.Scopes.Profile, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.OfflineAccess);
x.AllowAuthorizationCodeFlow();
x.AddDevelopmentEncryptionCertificate().AddDevelopmentSigningCertificate();
x.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableLogoutEndpointPassthrough()
.EnableTokenEndpointPassthrough()
.EnableUserinfoEndpointPassthrough()
.EnableStatusCodePagesIntegration();
})
.AddValidation(x => {
x.UseLocalServer();
x.UseAspNetCore();
});
And I have the following client:
OpenIddictApplicationDescriptor spa = new OpenIddictApplicationDescriptor {
ClientId = "spa",
ClientSecret = "secret",
ConsentType = OpenIddictConstants.ConsentTypes.Implicit,
PostLogoutRedirectUris = {
new Uri("https://localhost:5002/oidc-signout")
},
RedirectUris = {
new Uri("https://localhost:5002/oidc-signin"),
new Uri("https://localhost:5002/oidc-silent-refresh")
},
Permissions = {
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Prefixes.Scope + "api"
},
Requirements = {
OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange
}
};
On the Angular Spa client application I am using the configuration:
const settings: UserManagerSettings = {
automaticSilentRenew: true,
authority: "https://localhost:5000",
client_id: 'spa',
client_secret: 'secret',
filterProtocolClaims: true,
loadUserInfo: true,
post_logout_redirect_uri: "https://localhost:5002/oidc-signout",
redirect_uri: "https://localhost:5002/oidc-signin",
response_mode: 'query',
response_type: 'code',
scope: 'openid profile email offline_access api',
silent_redirect_uri: 'https://localhost:5002/oidc-silent-refresh'
};
When I click on the SPA to login I am redirected and get the error:
The 'offline_access' scope is not allowed.
If I use it without 'offline_access' then everything works fine, e.g.:
scope: 'openid profile email api'
What am I missing?
The refresh token flow should be enabled before the offline_access scope can be used.
In your Startup.cs you should change this line:
x.AllowAuthorizationCodeFlow();
into something like this:
x.AllowAuthorizationCodeFlow().AllowRefreshTokenFlow();
There's also a GitHub issue related to your problem.

Identity Server redirect to React Native error

I have an Identity Server running.
I try to make an authentication from a React Native App.
I am using react-native-app-auth package to do authentication.
When I do login from the app, I have the Identity Server Login page that is loaded in a browser.
When I login with the good credential, Identity Server return me an error "The view 'Redirect' was not found..."
Do you know What's missing ?
I expect to be redirected to my app after success login ...
Here is my config:
Identity Server config :
public static Client GetMobileClient()
{
return new Client
{
ClientId = "mobile.code",
ClientName = "Mobile Client (Code with PKCE)",
RequireClientSecret = false,
RedirectUris = { "com.server.acc:/oauthredirect" },
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
AllowedScopes = { "openid", "profile" , "email", "api.read" },
AllowOfflineAccess = true
};
}
And here is my React Native Config:
Build.gradle
manifestPlaceholders = [ appAuthRedirectScheme: 'com.server.acc' ]
Login.tsx:
import { authorize, refresh, AuthConfiguration } from 'react-native-app-auth';
...
const config: AuthConfiguration = {
issuer: 'https://acc.server.com:44344',
clientId: 'mobile.code',
redirectUrl: 'com.server.acc:/oauthredirect',
scopes: ['openid', 'profile', 'email', 'api.read']
};
const authState = await authorize(config);
So once I do "await authorize(config);", we have the login page that is loaded, after putting the good credentials, I have this error :
Why is he looking for .cshtml pages ???
Many Thanks ! I am blocked during 3 days for this !
Not sure ,but perhaps you should add HTTPS:// infront of the URL here:
redirectUrl: 'com.server.acc:/oauthredirect',

Keycloak backchannel login with .NET core api?

According to this OpenID spec https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html
OpenID Connect Client Initiated Backchannel Authentication Flow is an authentication flow like OpenID Connect. However, unlike OpenID Connect, there is direct Relying Party to OpenID Provider communication without redirects through the user's browser. This specification has the concept of a Consumption Device (on which the user interacts with the Relying Party) and an Authentication Device (on which the user authenticates with the OpenID Provider and grants consent). This specification allows a Relying Party that has an identifier for a user to obtain tokens from the OpenID Provider. The user starts the flow with the Relying Party at the Consumption Device, but authenticates and grants consent on the Authentication Device.
I'm trying to do the same with my .NET core api using Keycloak as the IdentityProvider. This is current working setup with Authorization Code Flow
var oidcOptions = new OpenIdConnectAuthenticationOptions()
{
AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,
ClientId = Application.Config.KeycloakConfig.Default.ClientId,
Authority = Application.Config.KeycloakConfig.Default.Authority,
RedirectUri = Application.Config.KeycloakConfig.Default.SiteManagementAuthRedirectUri,
ClientSecret = Application.Config.KeycloakConfig.Default.ClientSecret,
RequireHttpsMetadata = false,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Scope = "openid",
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
RequireExpirationTime = true,
IssuerValidator = (issuer, securityToken, validationParameters) =>
{
if (issuer != Application.Config.KeycloakConfig.Default.Authority)
throw new SecurityTokenInvalidIssuerException("Invalid issuer");
return issuer;
},
ValidAudience = Application.Config.KeycloakConfig.Default.ClientId
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
RedirectToIdentityProvider = OnRedirectToIdentityProvider
}
};
appBuilder.UseOpenIdConnectAuthentication(oidcOptions);
I managed to get the tokens using password grant as below
HTTP POST {{KeyCloakUrl}}/realms/My-Realms/protocol/openid-connect/token
{
grant_type: "password",
client_id: "Keycloak_client_id",
client_secret: "***",
username: "username i created in Keycloak",
password: "***",
response_type : "code id_token",
scope: "openid"
}
Reponse:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI***********",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJ********",
"token_type": "bearer",
"id_token": "eyJhbG**********",
"not-before-policy": 0,
"session_state": "c2803e20-bc04-4a9c-9b1a-d1fd3dfd1f22",
"scope": "openid email profile"
}
Question: Is it possible to manual make a POST request with id_token to the .NET core api to authenticate the requests and how to do it?