ASP.NET Core Identity Server 4 Authorization Code PKCE
▌Introduction
If our
web application in on server side, e.q. SSR. We can use Authorization Code
Flow to exchange an Authorization Code for tokens.
The flow
is as following,
(Picture
from auth0.com)
As we can
see, the flow:
1. Pass the Authorization Code thru URL/URL schema.
2. Use Authorization Code + Client ID + Client
Secret to get the id_token and access_token.
However
the Authorization Code may be hacked, also in public client, such as native
mobile application or SPA (single page application), the Client Secret is
hardly to be protected.
So it is
suggested to integrate PKCE (Proof Key
for Code Exchange) with Authorization
Code Flow.
The PKCE Authorization Code flow was specified
in RFC7636 and its flow is as
following,
In this tutorial,
we will implement the PKCE Authorization Code Flow with cookie-based authorization
that is based on Identity Server 4.
Here is
the final result’s demo.
▋Related articles
01. [OpenLDAP] Create an OpenLDAP container
02. [ASP.NET Core] Identity Server 4 – Concepts
03. [ASP.NET Core] Identity Server 4 – LDAP authentication
04. [ASP.NET Core] Identity Server 4 – Secure Web API
05. [ASP.NET Core] Identity Server 4 – Custom Event Sink
06. [ASP.NET Core] Identity Server 4 – Refresh Token
07. [ASP.NET Core] Identity Server 4 – Role based authorization
08. [ASP.NET Core] Identity Server 4 – Policy based authorization
09. [ASP.NET Core] Identity Server 4 - Dockerize
10. [ASP.NET Core] Identity Server 4 – Client Credential
11. [ASP.NET Core] Identity Server 4 – Policy based authorization with custom Authorization Handler
12. [ASP.NET Core] Identity Server 4 – Signing credential
13. [ASP.NET Core] Identity Server 4 – Authenticate by multiple LDAP
14. [ASP.NET Core] Identity Server 4 – Cache and refresh Discovery document
15. [ASP.NET Core] Identity Server 4 – PKCE Authorization Code Flow
16. [ASP.NET Core] Identity Server 4 – PKCE Authorization Code Flow (Javascript client)
▌Environment
▋Docker 18.05.0-ce
▋.NET Core SDK 3.1.201
▋IdentityServer4 3.1.2
▋IdentityModel 4.0.0
▌Implement
The
source code is on my Github.
▋PKCE Client configuration on Auth Server
Go to Idsrv4 project (Auth Server), and open InMemoryInitConfig.cs
to set the below configuration on a new client:
▋InMemoryInitConfig.cs
Notice that there are some key settings:
Configuration |
Description |
Value |
RedirectUris |
The
allowed Uri(s) to return Authorization Code or Tokens. |
E.q.
"https://client-app/signin-oidc" |
RequireConsent |
If
enabled, the user will be redirected to the consent page after sign-in. |
Boolean,
default: true. |
RequirePkce |
Whether
a proof key is a must for requesting Authorization Code. |
Boolean,
default: false. |
AllowPlainTextPkce |
Send
a proof key by plain method. (not
recommended) |
Boolean,
default: false. |
▋Enable cookie-based authentication and Authorization Code
Flow on client
▋Startup.cs: ConfigureServices
Now we can only add [Authorize] to the protected
route(s) as following,
This will result in redirecting to the Authentication prompt (sign-in page) in Auth Server.
▋Auth Server’s Sign-in and Consent pages
We can follow the idsrv4 template to create the
sign-in and consent pages on Auth Server.
I refactored some of the codes from the template in
my sample
code.
▋Sign-in page
▋Consent page
▋How the flow steps through
1. When a user who is not signed in, the client application will first
send Authorization Code request to Auth
Server’s URL: /connect/authorize
with a random Code Challenge (URL safe base64 string).
The /connect/authorize
url contains the following parameters.
(Table 1.)
URL parameter |
Value |
Description |
client_id |
PkceCodeBackend |
The Client Id |
redirect_uri |
https://localhost:5001/signin-oidc |
|
response_type |
code |
|
Scope |
openid profile MyBackendApi2 offline_access |
|
code_challenge_method |
S256 |
|
code_challenge |
uc6gNUTWAnwgwAo4O3QCRxLw8fFniR36vrA_2WMPxQo |
URL safe base64 |
response_mode |
form_post |
|
Nonce |
637455834911251586.ZDNhN… |
Nonce is used to associate a Client session with an ID Token.
It serves as a token validation parameter to mitigate replay attacks. See OpenID
Connect specification. |
State |
CfDJ8LH7J_bUBzNAlMjrmdBfJia0f… |
State is to protect the end user from cross site request
forgery (CSRF) attacks. See OAuth 2.0 protocol RFC6749. |
x-client-SKU |
ID_NETSTANDARD2_0 |
The metadata of Identity Server 4. |
x-client-ver |
5.5.0.0 |
The metadata of Identity Server 4. |
Then Auth Server will redirect the
user to /Account/Login?RedirectUrl= with the
url parameter: RedirectUrl.
The RedirectUrl contains the URL encoded string as
following.
If you decode the value, you will get
exactly the same information as the Table 1.
URL parameter |
Value |
Description |
ReturnUrl |
%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DPkceCodeBackend%26redirect_uri%3Dhttps%253A%252F%252F172.23.131.181%253A5001%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520MyBackendApi2%2520offline_access%26code_challenge_method%3DS256%26code_challenge%3Duc6gNUTWAnwgwAo4O3QCRxLw8fFniR36vrA_2WMPxQo%26response_mode%3Dform_post%26nonce%3D6374558349BAXebbSohHgE%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D5.5.0.0
HTTP/1.1 |
URL encoded string |
In this step, the user had been redirected to the login page of Auth Server.
2. User entered his/her ID/PWD and submitted. The Auth Server
authenticated the user and redirect to the consent page, then the user
submitted on the consent page.
In this step, the following urls (inside red block) contains the same
information as Table 1.
3. Finally, the Auth Server sent back the Authorization Code thru
the redirect_url:
https://localhost:5001/signin-oidc.
And the user was redirected to the original url on client side: /OpenId/Login.
And client side used the Authorization Code + Code Verifier to get the access
token thru Auth Server’s API: /connect/token.
▋Source Code
Github: KarateJB/AspNetCore.IdentityServer4.Sample
▌Reference
▋Authorization
Code Flow with Proof Key for Code Exchange (PKCE)
Great overview of PKCE in Identity Server 4! For hosting ASP.NET Core apps, check out TSO Host for excellent service.
回覆刪除