When trying to login to identityserver (using .net core 3 preview) I get Invalid redirect_uri error even though the request uri and the allowed one are identical.
What else could I be doing wrong?
fail: IdentityServer4.Validation.AuthorizeRequestValidator[0]
Invalid redirect_uri: http://localhost:1337/authentication/login-callback
{
"ClientId": "myapp",
"ClientName": "myapp",
"AllowedRedirectUris": [
"http://localhost:1337/authentication/login-callback"
],
"SubjectId": "anonymous",
"RequestedScopes": "",
"Raw": {
"client_id": "myapp",
"redirect_uri": "http://localhost:1337/authentication/login-callback",
"response_type": "id_token token",
"scope": "webAPI openid profile",
"state": "5a10fc5a7006475c8d3a348c711ca58a",
"nonce": "ae6f9f35837241e1ba3841c2ff8a4fce",
"prompt": "none"
}
}
fail: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
Request validation failed
I would like to add for whoever needs a more in depth explanation that the reason this doesn't work for IdentityServerSPA
client types is the fact that when you call AddApiAuthorization
thus:
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
The library code runs this from the file IdentityServerBuilderConfigurationExtensions.cs line 65 does this:
builder.AddAspNetIdentity<TUser>()
.AddOperationalStore<TContext>()
.ConfigureReplacedServices() // <-- This is the line
.AddIdentityResources()
.AddApiResources()
.AddClients()
.AddSigningCredentials();
And ConfigureReplacedServices
does this:
builder.Services.AddSingleton<IRedirectUriValidator, RelativeRedirectUriValidator>();
And RelativeRedirectUriValidator
validates the redirect URI by first checking if the client type is IdentityServerSPA
or not, thus:
public override Task<bool> IsRedirectUriValidAsync(string requestedUri, Client client)
{
if (IsLocalSPA(client))
{
return ValidateRelativeUris(requestedUri, client.RedirectUris);
}
else
{
return base.IsRedirectUriValidAsync(requestedUri, client);
}
}
When IsLocalSPA
is defined thus:
private static bool IsLocalSPA(Client client) =>
client.Properties.TryGetValue(ApplicationProfilesPropertyNames.Profile, out var clientType) &&
ApplicationProfiles.IdentityServerSPA == clientType;
I add this answer both to help others, and to help myself understand this better :)
It might not be the same issue (I am far from being and expert here). But I did have the same problem which made me find this article.
I found in my case, the problem was a missing trailing / on the return url. This github issue triggered me: https://github.com/dotnet/aspnetcore/issues/21167. Look down a bit for a comment by JefSchraag on May 1, 2020.
This modification in the RedirectToLogin.razor component in my client project seemed to solve the problem.
protected override void OnInitialized()
{
var returnUrl = Navigation.Uri;
if (!returnUrl.EndsWith('/'))
{
returnUrl += '/';
}
Navigation.NavigateTo($"authentication/login?returnUrl={returnUrl}");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With