lnik-m
December 12, 2024, 9:29pm
1
Minimal reproduction of the problem
Hello! I would like to receive a Squidex token from my web application using an Authorization Code flow instead of a Client Credentials flow. Is it possible?
If so, could you tell me what headers I should pass, what the /authorization endpoint is and where I can set the allowed redirect_uris
I saw an article where allowedGrantTypes includes an authorization code (Identity Server in Load Balancer environment in Azure - #7 by Sebastian ) but I am not sure if it is what I look for and it is not deprecated
Environment
App Name: test-squidex-integration
Self hosted with docker
Self hosted with IIS
Self hosted with other version
Cloud version
Version: 7.6.1
Browser:
Chrome (desktop)
Chrome (Android)
Chrome (iOS)
Firefox
Safari (desktop)
The article has nothing to do with your problem.
Why do you need authorization code flow? This is used to authenticate users, not machines and therefore it has never been implemented.
lnik-m
December 13, 2024, 11:24am
3
I want to use Authorization Code flow to get rid of clientSecret in my .env to provide more security. Currently I get access_token with Client Credentials flow as written in Dev Guides (Authentication | Squidex )
So, there is no way to get access_token without clientSecret for now?
Authorization code flow authenticates users. So this would only work, if …
A) Your site is only built for internal users that are also content editors in Squidex.
B) Every user of your site is also a Squidex user.
If you want to improve security you have 3 options:
Create a client in Squidex with only the necessary permissions and set it to AllowAnonymous. Then you don’t need an access_token at all
If your env file is for the frontend (e.g. React SPA), create a proxy to handle the authentication in your backend.
Use a framework with SSR support and only access the client credentials in server components.
lnik-m
December 13, 2024, 12:12pm
5
Let’s sum it up
As I understood, the way B of getting access_token has never been implemented in Squidex and I should use proxy
In my case:
Squidex is hosted on my domain (e.x. https://lnik-m )
it is React SPA
Create a client in Squidex with only the necessary permissions and set it to AllowAnonymous. Then you don’t need an access_token at all
AllowAnonymous doesn’t work for me because I need to get profile, email and permissions of Squidex user to log changes
The way A : how authorization is implemented by now:
user signs up through SSO
if user signed up successfully, I fetch Squidex access_token by client credentials (it works fine ):
fetch(‘https://lnik-m/squidex/identify-server’, {
method: ‘POST’,
headers: {
‘Content-type’: ‘application/x-www-form-urlencoded’
},
body: `client_id=${clientId}&client_secret=${clientSecret}&scope=squidex-api&grant_type=client_credentials`
})
The way B : how I tried to implement Authorization Code flow (doesn’t work ):
fetch(‘https://lnik-m/squidex/identify-server’, {
method: ‘POST’,
headers: {
‘Content-type’: ‘application/x-www-form-urlencoded’
},
body: `client_id=${clientId}&scope=squidex-api&grant_type=authorization_code&redirect_uri=https://lnik-m/`
})
But then the main reason is that you want to authenticate in the name of the user. You want to have the user claims (e.g. permissions).
Most permissions are not stored in the claims though, they are given by assigning users to apps.
Authorization code flow is actually allowed for the frontend:
builder.RegisterScopes(
Scopes.Email,
Scopes.Profile,
Scopes.Roles,
Constants.ScopeApi,
Constants.ScopePermissions);
builder.AllowClientCredentialsFlow();
builder.AllowImplicitFlow();
builder.AllowAuthorizationCodeFlow();
builder.UseAspNetCore()
.DisableTransportSecurityRequirement()
.EnableAuthorizationEndpointPassthrough()
.EnableLogoutEndpointPassthrough()
.EnableStatusCodePagesIntegration()
.EnableTokenEndpointPassthrough()
.EnableUserinfoEndpointPassthrough();
builder.SetAccessTokenLifetime(TimeSpan.FromDays(30));
But to use that you need a client, which allows the flow and where you register the redirect URIs, similar to this:
Permissions.Prefixes.Scope + Constants.ScopePermissions
}
});
}
private static IEnumerable<(string, OpenIddictApplicationDescriptor)> CreateStaticClients(IServiceProvider serviceProvider)
{
var urlGenerator = serviceProvider.GetRequiredService<IUrlGenerator>();
var frontendId = Constants.ClientFrontendId;
yield return (frontendId, new OpenIddictApplicationDescriptor
{
DisplayName = "Frontend Client",
ClientId = frontendId,
ClientSecret = null,
RedirectUris =
{
new Uri(urlGenerator.BuildUrl("login;")),
new Uri(urlGenerator.BuildUrl("client-callback-silent.html", false)),
new Uri(urlGenerator.BuildUrl("client-callback-popup.html", false))
},
If you need this, please create a PR for that.
Just add the necessary properties to the options class: squidex/backend/src/Squidex/Config/MyIdentityOptions.cs at master · Squidex/squidex · GitHub
Then create the client from this class in the ApplicationStore class mentioned above.
You basically need
Client ID
Client Name (optional, can be same as ID)
Logout Redirect URL (s)
Login Redirect URL(s)