Logout redirect causes this error:
{“errorCode”:“invalid_client”,“errorSummary”:“Invalid value for ‘client_id’ parameter.”,“errorLink”:“invalid_client”,“errorId”:“oae048s3hWISeippGnzrmdjgQ”,“errorCauses”:[]}
Any ideas?
Thanks
Logout redirect causes this error:
{“errorCode”:“invalid_client”,“errorSummary”:“Invalid value for ‘client_id’ parameter.”,“errorLink”:“invalid_client”,“errorId”:“oae048s3hWISeippGnzrmdjgQ”,“errorCauses”:[]}
Any ideas?
Thanks
Can you please provide more information about your application? Are you using .NET, Java and Spring Boot, Angular, or React, etc?
I have a Web Forms Aspnet aplicattion in VB.net.
My okta configutarion:
Login redirect URIs: http://localhost:16517/authorization-code/callback
Logout redirect URIs: http://localhost:16517/
Key en Web.config
add key=“okta:RedirectUri” value=“http://localhost:16517/authorization-code/callback”
add key=“okta:PostLogoutRedirectUri” value=“http://localhost:16517/”
Master Page with Logout Event
<asp:LoginStatus
ID=“HeadLoginStatus”
runat=“server”
LogoutAction=“Redirect”
LogoutText=“Cerrar Session”
LogoutPageUrl="~/"
OnLoggingOut=“LoggingStatus_LoggingOut”/>
And the code behind:
Protected Sub LoggingStatus_LoggingOut(ByVal sender As Object, ByVal e As LoginCancelEventArgs)
Context.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType)
End Sub
Does the client ID you have configured work for logging in and you’re only having issues logging out?
Thats correct. With Login no problem.
Hi @nrodrigu,
Can you also post your OIDC configuration?
When logging out you have to pass the id_token_hint
param. You can find more info about it here: https://developer.okta.com/docs/reference/api/oidc/#request-parameters-5. Are you passing your Id Token when logging out?
Hi. This is the Startup.vb class:
<Assembly: OwinStartup(“PruebasOkta”, GetType(AspNetWebFormsOkta.Startup))>
Namespace AspNetWebFormsOkta
Public Class Startup
Private ReadOnly _clientId As String = ConfigurationManager.AppSettings(“okta:ClientId”)
Private ReadOnly _redirectUri As String = ConfigurationManager.AppSettings(“okta:RedirectUri”)
Private ReadOnly _authority As String = ConfigurationManager.AppSettings(“okta:OrgUri”)
Private ReadOnly _clientSecret As String = ConfigurationManager.AppSettings(“okta:ClientSecret”)
Public Sub Configuration(ByVal app As IAppBuilder)
ConfigureAuth(app)
End Sub
Public Sub ConfigureAuth(ByVal app As IAppBuilder)
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions())
app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions With {
.ClientId = _clientId,
.ClientSecret = _clientSecret,
.Authority = _authority,
.RedirectUri = _redirectUri,
.ResponseType = OpenIdConnectResponseType.CodeIdToken,
.Scope = OpenIdConnectScope.OpenIdProfile,
.TokenValidationParameters = New TokenValidationParameters With {
.NameClaimType = "name"
},
.Notifications = New OpenIdConnectAuthenticationNotifications With {
.AuthorizationCodeReceived = Async Function(n)
Dim tokenClient = New TokenClient($"{_authority}/v1/token", _clientId, _clientSecret)
Dim tokenResponse = Await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri)
If tokenResponse.IsError Then
Throw New Exception(tokenResponse.[Error])
End If
Dim userInfoClient = New UserInfoClient($"{_authority}/v1/userinfo")
Dim userInfoResponse = Await userInfoClient.GetAsync(tokenResponse.AccessToken)
Dim claims = New List(Of Claim)(userInfoResponse.Claims) From {
New Claim("id_token", tokenResponse.IdentityToken),
New Claim("access_token", tokenResponse.AccessToken)
}
n.AuthenticationTicket.Identity.AddClaims(claims)
End Function
}
})
End Sub
End Class
End Namespace
And the Application configuration:
Thanks
Hi @nrodrigu,
You will also need to add an additional notification for RedirectToIdentityProvider
to append the id_token
when you are logging out. Something like this with C#:
private Task BeforeRedirectToIdentityProviderAsync(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> redirectToIdentityProviderNotification)
{
// If signing out, add the id_token_hint
if (redirectToIdentityProviderNotification.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
if (redirectToIdentityProviderNotification.OwinContext.Authentication.User.FindFirst("id_token") != null)
{
redirectToIdentityProviderNotification.ProtocolMessage.IdTokenHint = redirectToIdentityProviderNotification.OwinContext.Authentication.User.FindFirst("id_token").Value;
}
}
}
...
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync,
....
},
I hope this helps.
Excuse me where should I put that code, it is not clear to me
Sure! So, in your Startup class when initializing the OIDC middleware, you are already overwriting the OpenIdConnectAuthenticationNotifications
by adding your own logic when the authorization code is received (AuthorizationCodeReceived):
New OpenIdConnectAuthenticationNotifications With {
.AuthorizationCodeReceived = Async Function(n)
...
OpenIdConnectAuthenticationNotifications
has other delegates that you can also use to provide your custom code, RedirectToIdentityProvider
is one of them. You should add another function for RedirectToIdentityProvider
to include the id token hint if the request type is Logout
. I’m not familiar with VB, but I imagine you can do something like this:
...
.Scope = OpenIdConnectScope.OpenIdProfile,
.TokenValidationParameters = New TokenValidationParameters With {
.NameClaimType = "name"
},
.Notifications = New OpenIdConnectAuthenticationNotifications With {
.AuthorizationCodeReceived = Async Function(n)
// your current code ...
.RedirectToIdentityProvider = Async Function(n)
// your code to send IdTokenHint if logging out as shown in BeforeRedirectToIdentityProviderAsync
...
Hopefully this is clear now.
Hi Laura. I modified the code, this way:
Public Sub ConfigureAuth(ByVal app As IAppBuilder)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions())
app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions With {
.ClientId = _clientId,
.ClientSecret = _clientSecret,
.Authority = _authority,
.RedirectUri = _redirectUri,
.ResponseType = OpenIdConnectResponseType.CodeIdToken,
.Scope = OpenIdConnectScope.OpenIdProfile,
.PostLogoutRedirectUri = _PostLogoutRedirectUri,
.TokenValidationParameters = New TokenValidationParameters With {
.NameClaimType = "name"
},
.Notifications = New OpenIdConnectAuthenticationNotifications With {
.AuthorizationCodeReceived = Async Function(n)
Dim tokenClient = New TokenClient(_authority & "/v1/token", _clientId, _clientSecret)
Dim tokenResponse = Await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri)
If tokenResponse.IsError Then
Throw New Exception(tokenResponse.[Error])
End If
Dim userInfoClient = New UserInfoClient($"{_authority}/v1/userinfo")
Dim userInfoResponse = Await userInfoClient.GetAsync(tokenResponse.AccessToken)
Dim claims = New List(Of Claim)(userInfoResponse.Claims) From {
New Claim("id_token", tokenResponse.IdentityToken),
New Claim("access_token", tokenResponse.AccessToken)
}
n.AuthenticationTicket.Identity.AddClaims(claims)
Return
End Function,
.RedirectToIdentityProvider = Function(n)
If n.ProtocolMessage.RequestType = OpenIdConnectRequestType.Logout Then
Dim idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token")
If idTokenClaim IsNot Nothing Then
n.ProtocolMessage.IdTokenHint = idTokenClaim.Value
End If
End If
Return Task.CompletedTask
End Function
}
})
End Sub
And a concern arises. When debugging the application I see that when I perform the LogOut action (Context.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType)) the function associated with the RedirectToIdentityProvider runs twice.
Now, is my code well generated according to your instructions and why does the above happen?
Thank you
Hi @nrodrigu,
Your code looks good to me. The RedirectToIdentityProvider
is an event that runs multiple times, basically, any time you are about to redirect to the Identity Provider (Okta) but by doing this n.ProtocolMessage.RequestType = OpenIdConnectRequestType.Logout
you are ensuring that your code inside that if
block will run only for logout. Is that code executed twice? Is log out working now?
Hello Laura. Sorry for the delay. Log Out works now. But now I have another problem. When Okta redirects to my website I get the following error:
IDX21323: RequireNonce is ‘System.Boolean’. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don’t need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to ‘false’. Note if a ‘nonce’ is found it will be evaluated.
I have added a line of code that I found searching the internet and that was supposed to fix the problem, but it has not solved it.
app.UseKentorOwinCookieSaver()
Any ideas? Thank you
Here is the code in C#:
RedirectToIdentityProvider = n =>
{
// If signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenClaim != null)
{
n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
}
}
return Task.CompletedTask;
}