From 3cf5463c08a901e752007ee2c674c929eee9929f Mon Sep 17 00:00:00 2001 From: konarfil Date: Mon, 25 Sep 2023 12:40:16 +0200 Subject: [PATCH] PKCE implementation --- src/css/style.css | 9 +- src/flow/code-1.html | 13 +-- src/flow/code-2.html | 2 +- src/flow/code-3.html | 2 +- src/flow/pkce-1.html | 141 +++++++++++++++++++++++++ src/flow/pkce-2.html | 190 ++++++++++++++++++++++++++++++++++ src/flow/pkce-3.html | 124 ++++++++++++++++++++++ src/flow/pkce-4.html | 241 +++++++++++++++++++++++++++++++++++++++++++ src/index.html | 4 +- src/js/cookies.js | 12 +++ 10 files changed, 722 insertions(+), 16 deletions(-) create mode 100644 src/flow/pkce-1.html create mode 100644 src/flow/pkce-2.html create mode 100644 src/flow/pkce-3.html create mode 100644 src/flow/pkce-4.html create mode 100644 src/js/cookies.js diff --git a/src/css/style.css b/src/css/style.css index 1e4a641..2ebe575 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -93,11 +93,18 @@ body { align-items: center; justify-content: center; position: relative; - width: 70%; margin: 0 auto; margin-top: 40px; } +.circle-3 { + width: 70%; +} + +.circle-4 { + width: 80%; +} + .circle { width: 50px; height: 50px; diff --git a/src/flow/code-1.html b/src/flow/code-1.html index 270c320..1bbac6b 100644 --- a/src/flow/code-1.html +++ b/src/flow/code-1.html @@ -21,7 +21,7 @@

Authorization Code Flow

-
+
1
@@ -119,17 +119,8 @@
+ + + + +
+
+
+

PKCE Flow

+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+
+ Create a secret code verifier and code challenge +
+
+ Build the authorization URL and redirect the user to the authorization server +
+
+ After the user is redirected back to the client, verify the state +
+
+ Exchange the authorization code and code verifier for an access token +
+
+
+
+
+
+
+
+
1. Create a Code Verifier and Challenge
+

Before we can start the authorization process, we need to create a code verifier and a code challenge. The code verifier is a cryptographically random string that is used to verify the identity of the client. The code challenge is a hashed version of the code verifier, which is sent to the authorization server. The authorization server will then compare the code challenge with the code verifier to verify the identity of the client.

+

+
+
+
Generate Code Verifier
+
+
+ +
+
+ +

Now that we habe the code verified, we need to create the code challenge. We do so by hashing the code verifier using the SHA256 algorithm and then encoding it using the URL-safe Base64 encoding.

+ +
+
+
Generate Code Challenge
+
+
+ +
+
+ +

Now that we have the code verifier and code challenge, we can start the authorization process.

+

+
+ Continue +
+
+
+
+
+
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/src/flow/pkce-2.html b/src/flow/pkce-2.html new file mode 100644 index 0000000..4c86917 --- /dev/null +++ b/src/flow/pkce-2.html @@ -0,0 +1,190 @@ + + + + + + OAuth 2.0 Playground - PKCE Flow (2/4) + + + + + + + + + + + + +
+
+
+

PKCE Flow

+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+
+ Create a secret code verifier and code challenge +
+
+ Build the authorization URL and redirect the user to the authorization server +
+
+ After the user is redirected back to the client, verify the state +
+
+ Exchange the authorization code and code verifier for an access token +
+
+
+
+
+
+
+
+
2. Build the Authorization URL
+

+ First we need to build the authorization URL and redirect the user to the authorization server. The URL is constructed as follows: +

+
+

Let's break it down...

+
    +
  • +

    +

    +

    URL of the authorization endpoint on the server. How is this path constructed will + differ between OAuth providers (such as Keycloak, Okta, etc.). +

    +
  • +
  • +

    response_type=

    +

    OAuth 2.0 response type. In this case, we are using the Authorization Code flow, so + we are requesting the authorization code.

    +
  • +
  • +

    client_id=

    +

    Client ID of the application. This is a public identifier for the client, and it is + used by the authorization server to identify the application + when redirecting the user back to the client.

    +
  • +
  • +

    redirect_uri=

    +

    Redirect URI of the client. This is the URL that the authorization server will + redirect the user back to after the user has logged in and + granted permissions. The redirect URI must match one of the URIs registered for the + client ID.

    +
  • +
  • +

    scope=

    +

    Scopes requested by the client. Scopes are used to limit the access of the access + token. In this case, we are requesting the offline_access scope, + which allows the client to obtain a refresh token.

    +
  • +
  • +

    state=

    +

    State parameter. This is an optional parameter that the client can use to maintain + state between the request and callback. The authorization + server includes this parameter when redirecting the user back to the client, + allowing the client to verify that the response is coming from the + server and not a malicious third party (CSRF attack).

    +
  • +
  • +

    code_challenge=

    +

    This is the code challenge we have created in the previous step. This ensures that even if an attacker intercepts the authorization code, they can't exchange it for an access token without the original code verifier.

    +
  • +
  • +

    code_challenge_method=

    +

    Code Challenge method tells the identity provider how the code_challenge was generated from the original code verifier. S256 means that + the challenge is a base64url encoding of the SHA-256 hash of the verifier. This is the recommended method for PKCE.

    +
  • +
+

All that we now need to do is click the button below and login with our credentials. + For the purposes of this + playground we already took the liberty to create user with password user for you. After your credentials are successfully verified, you will be redirected back to this playground, to the URL we have specified in the redirect_uri query parameter of the request.

+ +
+
+
+
+
+ +
+
+
+ + + + + diff --git a/src/flow/pkce-3.html b/src/flow/pkce-3.html new file mode 100644 index 0000000..7f2b388 --- /dev/null +++ b/src/flow/pkce-3.html @@ -0,0 +1,124 @@ + + + + + + OAuth 2.0 Playground - PKCE Flow (3/4) + + + + + + + + + + + + +
+
+
+

PKCE Flow

+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+
+ Create a secret code verifier and code challenge +
+
+ Build the authorization URL and redirect the user to the authorization server +
+
+ After the user is redirected back to the client, verify the state +
+
+ Exchange the authorization code and code verifier for an access token +
+
+
+
+
+
+
+
+
3. Verify the state parameter
+

You have now been redirected back to the application, to the page that was specified in the redirect-url parameter. In the URL you can notice, that there are addtional query parameters:

+
+

Let's break it down...

+
    +
  • +

    state=

    +

    The state parameter is an opaque value used by the client to maintain state between the request and the callback. + Essentially, it is used to prevent Cross-Site Request Forgery (CSRF) attacks and to ensure the response belongs to the request made by the client. +

    The state value isn't strictly necessary here since the PKCE parameters provide CSRF protection themselves. In practice, + if you're sure the OAuth server supports PKCE, you can use the state parameter for application state instead of using it + for CSRF protection.

    +

    +
  • +
  • +

    session_state=

    +

    The session state parameter is not a core part of the OAuth 2.0 specification, but it is used in OpenID Connect (OIDC) + to represent the state of the end user's session at the Authorization Server. + The client can use this value to help manage user sessions or to detect when the user's session at the Authorization + Server changes (for example, if the user logs out).

    +
  • +
  • +

    code=

    +

    The code parameter contains the actual authorization code. This is a temporary code that the client can exchange for an + access token (and optionally, a refresh token) by making a back-channel request to the Authorization Server. + The format and structure of the code is determined by the Authorization Server. It can be just a random string, or a more complex construction. The exact significance of this structure is specific to the Authorization Server implementation and might include different identifiers or information encoded in + the structure.

    +
  • +
+

Now we have everything necessary to obtain token for the user. But is the state we have sent equivalent to the one we received back?

+ +
+
+
+
+
+ +
+
+
+ + + + diff --git a/src/flow/pkce-4.html b/src/flow/pkce-4.html new file mode 100644 index 0000000..ecb21ac --- /dev/null +++ b/src/flow/pkce-4.html @@ -0,0 +1,241 @@ + + + + + + OAuth 2.0 Playground - PKCE Flow (4/4) + + + + + + + + + + + + +
+
+
+

PKCE Flow

+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+
+ Create a secret code verifier and code challenge +
+
+ Build the authorization URL and redirect the user to the authorization server +
+
+ After the user is redirected back to the client, verify the state +
+
+ Exchange the authorization code and code verifier for an access token +
+
+
+
+
+
+
+
+
4. Exchange the code and code verifier for token
+

Now that we have the authorization code, we can exchange it for an access token. This is done by sending a POST request to the token endpoint.

+
+

With body data:

+
+ Let's break it down...

+
    +
  • +

    +

    The token endpoint URL

    +
  • +
  • +

    grant_type=

    +

    The grant type, in this case authorization_code

    +
  • +
  • +

    client_id=

    +

    Client ID of the application. This is a public identifier for the client, and it is + used by the authorization server to identify the application + when redirecting the user back to the client.

    +
  • +
  • +

    redirect_uri=

    +

    The redirect URI

    +
  • +
  • +

    code=

    +

    This is the authorization code we got in the previous step and is used to obtain the + access token. +

    +
  • +
  • +

    code_verifier=

    +

    This is the code verifier we generated in the first step. It is used to verify the + identity of the client. +

    +
  • +
+ +
+
+
+
+
+ +
+
+
+ + + + + diff --git a/src/index.html b/src/index.html index f0501e2..214048d 100644 --- a/src/index.html +++ b/src/index.html @@ -73,8 +73,8 @@ access token, the client provides the original verifier. The server validates it against the stored challenge, ensuring added security against malicious interceptions.

-
- build Under construction +
+ Try it
diff --git a/src/js/cookies.js b/src/js/cookies.js new file mode 100644 index 0000000..965f72c --- /dev/null +++ b/src/js/cookies.js @@ -0,0 +1,12 @@ +function setCookie(name, value, minutes) { + const date = new Date(); + date.setTime(date.getTime() + (minutes * 60 * 1000)); + const expires = "; expires=" + date.toUTCString(); + document.cookie = name + "=" + value + expires + "; path=/"; +} + +function getCookie(name) { + var value = "; " + document.cookie; + var parts = value.split("; " + name + "="); + if (parts.length == 2) return parts.pop().split(";").shift(); +}