Using IdentityServer4, I'm implementing Code flow authorization on an existing system which supports only ResourceOwnerPassword grant type in IdentityServer and works well.
I got into a stage where the user is promoted to authenticate, then redirected to server connect/authorize/callback
After that it is not authenticating and coming back to the login page. From the log, I got the following:
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint for /connect/authorize/callback
ValidatedAuthorizeRequest
{
"ClientId": "demo",
"ClientName": "MVC Client Demo",
"RedirectUri": "http://localhost:5002/signin-oidc",
"AllowedRedirectUris": ["http://openidclientdemo.com:8001/signin-oidc",
"http://localhost:5002/signin-oidc"],
"SubjectId": "anonymous",
"ResponseType": "code id_token",
"ResponseMode": "form_post",
"GrantType": "hybrid",
"RequestedScopes": "openid profile default-api",
"State": "CfDJ8DU4Xalc7d9HttaFlZ-UaDhGsjeeEccTfNiNZFz3yYZI9MfXjrXo2TAzT9f6-F2VEdC7bWtcD7HRJgkqrh4t0oTAe_47IBfcm5Fsde9bVRorq-CHcL6_c15Vz1G5LJyEzqX6tyjhcZ2g3J2JjxD1PME1W7sq9YSddhQUJmxt4bVi70wdTtXXp0tH0SKyb0vLCs3eIjOln792nobaFOCM7r3VJ8BfXfpDm2pOOmBlR7zCCBxFCivwj7Zmy5Tu8Z09MvzOaLEkPBSL5i9GyxmGiB0P6osBPYEDyoRfgy2qDigH3QqLmLYjfE6NrgcgIGO9kgXuUT52XgALV_ZKjNbih-Y",
"Nonce": "636702233595840569.NGQ3NGVlODMtYTVhNy00MjM4LWFhNGQtNTFiZTE3ZjllZmUzNjU5MGNmNjktNjg3Yy00YmZlLWEwYWYtYmMzM2QxZmZlNjBk",
"Raw": {
"client_id": "demo",
"redirect_uri": "http://localhost:5002/signin-oidc",
"response_type": "code id_token",
"scope": "openid profile default-api",
"response_mode": "form_post",
"nonce": "636702233595840569.NGQ3NGVlODMtYTVhNy00MjM4LWFhNGQtNTFiZTE3ZjllZmUzNjU5MGNmNjktNjg3Yy00YmZlLWEwYWYtYmMzM2QxZmZlNjBk",
"state": "CfDJ8DU4Xalc7d9HttaFlZ-UaDhGsjeeEccTfNiNZFz3yYZI9MfXjrXo2TAzT9f6-F2VEdC7bWtcD7HRJgkqrh4t0oTAe_47IBfcm5Fsde9bVRorq-CHcL6_c15Vz1G5LJyEzqX6tyjhcZ2g3J2JjxD1PME1W7sq9YSddhQUJmxt4bVi70wdTtXXp0tH0SKyb0vLCs3eIjOln792nobaFOCM7r3VJ8BfXfpDm2pOOmBlR7zCCBxFCivwj7Zmy5Tu8Z09MvzOaLEkPBSL5i9GyxmGiB0P6osBPYEDyoRfgy2qDigH3QqLmLYjfE6NrgcgIGO9kgXuUT52XgALV_ZKjNbih-Y",
"x-client-SKU": "ID_NET",
"x-client-ver": "2.1.4.0",
"accessToken": "4155a526-2bb1-4d88-ba3a-21cb3a91f266",
"userId": "MQ=="
}
}
Showing login: User is not authenticated
It is not clear for me what caused the authentication failure, any idea?
TL;DR: default identityserver using http + chrome, doesn't work. Chrome enforces that cookies with SameSite=none
have also Secure
attribute, so you may have to either use HTTPS, or modify the cookie policy using @blow's answer. Chromium blog
A bit of context on Single Sign On and cookies,
A cookie is a piece of information that a server sends on a response
and the browser sends back on every subsequent request
.
When you login into identityserver, it sends back multiple cookies, one of them identifies your session. This cookie is being sent with the attribute SameSite=none
this allows any application that you browse to make a request to your identityserver and include this cookie with it. This way, the call to /connect/authorize
includes this cookie, and identityserver skips the login part. Voilà SSO.
Are you using Google Chrome
?
Google Chrome recently introduced a change where all cookies issued with the attribute SameSite=none
must include the Secure
attribute.
Those two attributes mean:
SameSite: Controls how the browser will behave when attaching the cookie to any request made to your site, based on the origin.
SameSite=strict
: does not send the cookie on requests made from sites different from the origin. This helps to prevent CSRF attacks.
SameSite=lax
: similar to strict
but cookies get sent when the user knowingly starts the request, by clicking a link or sending a form. Not being sent on requests initiated by scripts.
SameSite=none
: the cookies will get included no matter which origin they come from.
Secure: Indicates that the cookie has to be sent over HTTPS only.
IdentityServer issues those cookies with SameSite=none
. This means that when you're serving IdentityServer without HTTPS on local, and using chrome as browser, it won't log you in, because after you POST to the server your user & password, the response will include the session cookie but your browser (chrome) will refuse it because they're not marked as secure
but, marked as SameSite=none
, and this combination is not allowed.
The cause is explaned by Pablo Recalde answer, the right solutions is to use HTTPS.
Anyway, you can change SameSite
value by setting CookiesPolicyOptions
Setting it to SameSiteMode.Lax
you can force to use SameSite=Lax
at least.
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });