Add in custom Auth Providers
Kronos11 opened this issue · 28 comments
Again nice to have feature request:
Add in capability to add in custom authentication and authorization providers
ex: AzureAd
Hi @Kronos11
At this moment, Esquio allow to configure different OpenId providers like Azure Ad, Identity Server, Auth0 etc!
Can you explain more this feature requests?
Maybe I just need more documentation to figure out how to use AzureAd
I'm used to using authentication.AddAzureAd()
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "mycompany.onmicrosoft.com",
"TenantId": "tenantId",
"ClientId": "clientId"
},
"OpenId": {
"ClientId": "interactive.public",
"Audience": "api",
"Authority": "https://demo.identityserver.io/",
"ResponseType": "code",
"RequireHttpsMetadata": "true"
}
You don’t need azure ad, this is a open Id connect provider and can be configured with AddOpenIdConnect.
This is a sample of that
.AddOpenIdConnect("aad", "Azure AD", options =>
{
options.ClientId = "[your-client-id]";
options.Authority = "https://login.windows.net/[your-tenant].onmicrosoft.com";
options.RequireHttpsMetadata = true;
options.ClientSecret = "[your-client-secret]";
options.UsePkce = true;
options.ResponseType = "code id_token";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
awesome, thanks for the assist. This can be closed
Hey @unaizorrilla sorry to bring this back up, but what you put above doesn't seem to quite work.
I see that there is also a BlazorClientSettingsMiddleware that is doing some work as well using the Security:OpenId
So it seems like we must use the AppSettings file to setup security
Hi @Kronos11
Sorry but I don't understand the issue:
- Security section is used to configure the AddJwtBearer on the HTTP API and also the blazor client.
- BlazorClientSettingsMiddleware is used to avoid issues with appsettings.json as static content, this return the settings from the configuration instead the normal way on blazor reading the static content, this allow to be modified by envars on docker etc...
You can check how to use AddOpenIdConnect / AddJwtBearer with Azure AD but at the end, this is a normal OpenIdProvider, the only thing is how to create the client Id ( application registration on Azure AD ) and the url for the authorization endpoint etc...
There is a step by step guide
https://www.ashleyhollis.com/how-to-configure-azure-active-directory-with-identityserver4
Apologies for not being very clear.
Let me explain what I'm running into and we can decide if something needs to be adjusted.
My organization has Azure AD that we use for all of our Authentication. I've primarily used OIDC as follows:
- Client
Configured to use OIDC as a client
scope: api-access - API
This is configured with delegated permissions for api-access
authorized with the client above
Setup in C# looks like the following
Blazor Client:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("{api-client}/api-access");
});
Api App:
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
How can I accomplish this type of auth with Esquio?
You don't need to do anything, except configure property Security:OpenId!
"Security": {
"DefaultSubjectId": "1", //default allowed subject id from demo.identityserver.io Alice user!!
"OpenId": {
"ClientId": "interactive.public",
"Audience": "api",
"Authority": "https://demo.identityserver.io/",
"ResponseType": "code",
"RequireHttpsMetadata": "true"
}
},
HTTP API is already configured to use this parameters on AddJwtBearer ( audience is the api scope )
Esquio/src/Esquio.UI.Host/Startup.cs
Line 53 in 1da6f5a
and Blazor Client is also prepared to use OpenId flow
Esquio/src/Esquio.UI.Client/Program.cs
Line 34 in 1da6f5a
If you want, I can prepare ( this night ) a sample using my Azure AD tenant and show you my configuration !
That would be great! thanks @unaizorrilla
Well, I have 5 minutes and I go to the pool :-)
First of all create two app registrations on azure ad, for http api and for the client ( esquio ui )
Esquio.UI.Api is and app registration for the API and expose a scope ( Expose API on Azure AD terminology )
On Esquio.UI app registration configure a redirect uri ( for debugging localhost:[port] )
Allow permissions ( Exposed api and profile )
This is my sample Security:OpenId configuration
"Security": {
"DefaultSubjectId": "[You-Need-To-Configure-Allowed-SubjectId]", //default allowed subject id from demo.identityserver.io Alice user!!
"OpenId": {
"ClientId": "762ed2b1-8107-44d5-9c9b-72c75749fb35",
"Audience": "api://c1cc1b6a-7580-49e5-8ab8-0f3cc9f97127/ui",
"Authority": "https://login.microsoftonline.com/bf3ae910-a895-44e6-aed1-0ed9601d9035/v2.0/",
"ResponseType": "code",
"RequireHttpsMetadata": "true"
}
}
And remember at this moment, Esquio UI get the user from
static class ClaimsPrincipalExtensions
{
public static string GetSubjectId(this ClaimsPrincipal principal)
{
return principal
.FindFirstValue(ApiConstants.SubjectNameIdentifier);
}
}
SubjectNameIdentifier is ClaimTypes.NameIdentifier , I think we can change this value from config :-) this will be a feature request to be accepted as PR!!
A mistake the reply uri by default with blazor add openid is with https://[domain]:[port]/authentication/login-callback
Just a point more... /token on azure ad does not allow to configure CORS ( MS some times it is so frustrating :-( ), in this case use a implicit flow instead!
Allow implicit flow on Esquio.UI app registration
and set response type as token
"Security": {
"DefaultSubjectId": "1", //default allowed subject id from demo.identityserver.io Alice user!!
"OpenId": {
"ClientId": "762ed2b1-8107-44d5-9c9b-72c75749fb35",
"Audience": "api://c1cc1b6a-7580-49e5-8ab8-0f3cc9f97127/ui",
"Authority": "https://login.microsoftonline.com/bf3ae910-a895-44e6-aed1-0ed9601d9035/v2.0/",
"ResponseType": "token",
"RequireHttpsMetadata": "true"
}
}
If the users/my return a 401 probably is because the azure ad include on access_token aud a different value that we specify on Audience, or a different issuer value that the authority :-( ( microsoft stupid things ) Probably we need to add Jwt override settings on V4 but in order to check ( only for debugging ) you can disable issuer,audience validation
.AddJwtBearer(options =>
{
Configuration.Bind("Security:OpenId", options);
options.TokenValidationParameters.ValidateIssuer = false;
options.TokenValidationParameters.ValidateAudience = false;
})
And just to sumarize :(
- this only work with implicit flow because AzureAd doesn't allow to configure CORS
- Probably you need to specify different settings for JWT because the token received could contain different values for issuer and audience
I'm so sorry for all comments :-(
Thanks so much for writing up all the instructions, it does help. I think I'm close, but I'm getting the following error right now in the console after logging in successfully:
Microsoft.JSInterop.JSException: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 130.. See InnerException for more details. ---> System.Text.Json.JsonException: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 130. ---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
Never see this error :-( can you clear site data and proceed again? I upload a branch samples/Kronos11-AzureAd with my sample working with my AD !
I try to add a new history to simplify different parameters between client and JWT for V4, meanwhile you can customize your UI
No matter what I do, I keep getting the above error and it also says:
warn: Esquio.UI.Client.Shared.Authentication[0]
User is not allowed to use Esquio App because subject is not configured.
Are you checked out my sample?
Are you configured de subject on settings?
Yes, here's my current config:
"DefaultSubjectId": "Craviotto, Kyle", // Which is what I see as the 'name' in the jwt
"OpenId": {
"ClientId": "{clientId}",
"Audience": "{clientId-api}/api-access",
"Authority": "https://login.microsoftonline.com/{tenanId}/v2.0/",
"ResponseType": "id_token",
"RequireHttpsMetadata": "true"
}
I realize it's slightly different, but I don't have access to customize my AD and only id_token response type works for me
Well, you need token also on response type! Try to gent this config on AAD
I got the token working correctly, but upon logging in I get an error in Authentication.razor:53
it looks like the Identity is not there for some reason
User System.Security.Claims.ClaimsPrincipal
Esquio.UI.Client.Shared.Authentication[0]
Error setting up the LoggedUserViewModel System.NullReferenceException: Object reference not set to an instance of an object.
at Esquio.UI.Client.Shared.Authentication.EvaluateAuthorization (System.Action notAllowed) [0x001a4]```
Looks like none of the claims are coming across even though I can clearly see them in the token
digging into this more, the reason it's not setting it up correctly is my organization is not sending me an id_token along with because implicit flow is disabled. I have to get them to enable it in order for this to work correctly.
Any thought about just using the claim information instead of an id_token?
By the way using the tutorial here:
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory?view=aspnetcore-3.1
Everything works correctly with my AD setup in an example app, it would be nice for this to be supported in Esquio as it's the microsoft recommended approach.
Hi @Kronos11
I'm not a fan of specific methods for Azure Ad like AddAzureAdBearer or AddMsalXXX because, well is specific and is not necesary, AzureAD is OpenId Provider and should work with AddOpenIdConnect and AddJwtBearer like any other OpenId providers like Identity Server, Auth0 etc
But well, we have a plan to modify, as I mentioned , the configuration to enable a better experience with Azure AD!!
If you configure azure ad app registration, as your link do, all will be work !
Hi @Kronos11
I'm working on this the new option on Azure AD for code + pkce on spa
Let working some days to create and scenario and docs!
Hi @Kronos11
I'm working on it!! branch features/azuread! Can you checkout, main interesting points
- We can set the claim type to use for permissions ( email on azure for example instead fixed subjectid)
- We reused the same configuration section
Still, main issue is on index.html because is not posible to register booth required scripts, i'm working on fix this issue
Hi @Kronos11
I'm working on it!! branch features/azuread! Can you checkout, main interesting points
- We can set the claim type to use for permissions ( email on azure for example instead fixed subjectid)
- We reused the same configuration section
Still, main issue is on index.html because is not posible to register booth required scripts, i'm working on fix this issue
Looking into this!
Hi @Kronos11
Updated the branch with register dynamic script depending on Azure or not :-) .... thanks @javiercn for your support on this!
Kyle we need to update docs for this scenarios on
https://github.com/Xabaril/Esquio/blob/features/azuread/docs/source/ui/deployment.rst
Can you contribute on this on feature/azuread branch before merging on master?