This commit is contained in:
konarfil
2023-09-25 15:43:43 +02:00
parent 3cf5463c08
commit dd89b5664c
9 changed files with 268 additions and 99 deletions

View File

@@ -62,13 +62,6 @@
Essentially, it is used to prevent Cross-Site Request Forgery (<a href="https://owasp.org/www-community/attacks/csrf" target="_blank">CSRF</a>) attacks and to ensure the response belongs to the request made by the client. Essentially, it is used to prevent Cross-Site Request Forgery (<a href="https://owasp.org/www-community/attacks/csrf" target="_blank">CSRF</a>) attacks and to ensure the response belongs to the request made by the client.
</p> </p>
</li> </li>
<li class="collection-item">
<p><b><span class="emphasis">session_state</span>=<span id="sessionState"></span></b></p>
<p>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).</p>
</li>
<li class="collection-item"> <li class="collection-item">
<p><b><span class="emphasis">code</span>=<span id="code"></span></b></p> <p><b><span class="emphasis">code</span>=<span id="code"></span></b></p>
<p>The code parameter contains the actual authorization code. This is a temporary code that the client can exchange for an <p>The code parameter contains the actual authorization code. This is a temporary code that the client can exchange for an
@@ -100,10 +93,8 @@
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code'); const code = urlParams.get('code');
const state = urlParams.get('state'); const state = urlParams.get('state');
const sessionState = urlParams.get('session_state');
$("#state").text(state); $("#state").text(state);
$("#sessionState").text(sessionState);
$("#code").text(code); $("#code").text(code);
function proceedToNextStep() { function proceedToNextStep() {

View File

@@ -101,50 +101,41 @@
<h6>Let's break down what we have received...</h6> <h6>Let's break down what we have received...</h6>
<ul class="collection"> <ul class="collection">
<li class="collection-item"> <li class="collection-item">
<p><b>access_token</b></p> <p><b>token_type</b></p>
<p>This is the actual access token, which allows the client application to access the user's protected resources on the <p>Indicates the type of token issued. In OAuth 2.0, the common type is "Bearer", which means that whoever bears
resource server (e.g., user profile, photos, etc.). the token
It's encoded as a JSON Web Token (JWT), which can be decoded to reveal a header, payload, and signature. can access the resources.</p>
The payload of the JWT contains claims about the user and the authentication event. For example, the iss claim indicates
the issuer of the token, the aud claim specifies the intended audience for the token, and the exp claim specifies the
expiration time of the token. <a href="https://jwt.io/" target="_blank">Want to see what's inside?</a></p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>expires_in</b></p> <p><b>expires_in</b></p>
<p>Indicates the number of seconds for which the <b>access_token</b> is valid. After this time, the access_token will expire and a <p>Indicates the number of seconds for which the <b>access_token</b> is valid. After this time, the access_token
new one must be obtained.</p> will expire and a
new one must be obtained.</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>refresh_expires_in</b></p> <p><b>access_token</b></p>
<p>Indicates the number of seconds for which the refresh_token is valid. Once the refresh token is expired, the client will <p>This is the actual access token, which allows the client application to access the user's protected resources
need to re-authenticate the user to get a new set of tokens.</p> on the
resource server (e.g., user profile, photos, etc.).
</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>refresh_token</b></p> <p><b>refresh_token</b></p>
<p>Used to obtain a new <b>access_token</b> when the current one expires. This allows the client to get a new <b>access_token</b> without <p>Used to obtain a new <b>access_token</b> when the current one expires. This allows the client to get a new
requiring the user to log in again. Like the <b>access_token</b>, it's encoded as a JWT.</p> <b>access_token</b> without
</li> requiring the user to log in again.
<li class="collection-item"> </p>
<p><b>token_type</b></p>
<p>Indicates the type of token issued. In OAuth 2.0, the common type is "Bearer", which means that whoever bears the token
can access the resources.</p>
</li>
<li class="collection-item">
<p><b>not-before-policy</b></p>
<p>Specifies a time before which the token should not be accepted. A value of 0 implies the token can be immediately used.</p>
</li>
<li class="collection-item">
<p><b>session_state</b></p>
<p>Represents the state of the user's session at the Authorization Server. This is the same value that could was
returned during the Authorization Code Flow in the <b>session_state</b> parameter.
It can be used in scenarios like OpenID Connect session management to monitor the user's session.</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>scope</b></p> <p><b>scope</b></p>
<p>Specifies the scopes granted by the user to the client application. Scopes determine the permissions associated with the <p>Specifies the scopes granted by the user to the client application. Scopes determine the permissions
<b>access_token</b>. Here, the granted scopes are email, offline_access, and profile. This means that with the provided access_token, the associated with the
client application can access the user's email and profile information and is also granted offline access (typically <b>access_token</b>. Here, the granted scopes are email, offline_access, and profile. This means that with
used in conjunction with refresh tokens).</p> the provided access_token, the
client application can access the user's email and profile information and is also granted offline access
(typically
used in conjunction with refresh tokens).
</p>
</li> </li>
</ul> </ul>
<p>And this concludes the Authorization Code Flow. Client application would now be able to request resources on users behalf without having to transfer his credentials with each request.</p> <p>And this concludes the Authorization Code Flow. Client application would now be able to request resources on users behalf without having to transfer his credentials with each request.</p>
@@ -161,7 +152,7 @@
<footer class="page-footer"></footer> <footer class="page-footer"></footer>
<script src="../js/load-layout.js"></script> <script src="../js/load-layout.js"></script>
<script> <script>
const tokenEndpoint = 'https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/token'; const tokenEndpoint = 'https://www.sso.oauth-playground.online/auth/token';
const clientID = 'oauth-playground'; const clientID = 'oauth-playground';
const code = new URLSearchParams(window.location.search).get('code'); const code = new URLSearchParams(window.location.search).get('code');

View File

@@ -153,7 +153,7 @@
return window.location.protocol + "//" + window.location.host + "/flow/code-2"; return window.location.protocol + "//" + window.location.host + "/flow/code-2";
} }
const baseUrl = "https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth"; const baseUrl = "https://www.sso.oauth-playground.online/auth";
const responseType = "code"; const responseType = "code";
const clientId = "oauth-playground"; const clientId = "oauth-playground";
const redirectUri = getRedirectUri(); const redirectUri = getRedirectUri();

169
src/flow/dag.html Normal file
View File

@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OAuth 2.0 Playground - Device Authorization Grant (1/3)</title>
<link rel="icon" href="../favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link type="text/css" rel="stylesheet" href="../css/style.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</head>
<body>
<header id="page-header"></header>
<main>
<div class="container">
<div class="section">
<h3 class="header centered">Device Authorization Grant</h3>
<div class="circle-container circle-3">
<div class="circle">
1
</div>
<div class="line line-inactive"></div>
<div class="circle circle-inactive">
2
</div>
<div class="line line-inactive"></div>
<div class="circle circle-inactive">
3
</div>
</div>
<div class="row">
<div class="col s4 circle-text">
Request a device code from the authorization server
</div>
<div class="col s4 circle-text">
Instruct the user where to enter the code
</div>
<div class="col s4 circle-text">
Poll the authorization server periodically until the code has been successfully entered
</div>
</div>
</div>
<div class="section">
<div class="col s12 m7">
<div class="card horizontal">
<div class="card-stacked">
<div class="card-content">
<h6>1. Request a Device Code</h6>
<p>
In order to initiate the <b>Device Authorization Grant</b>, we need to request a device code from the authorization server. The request is sent to the following URL:
</p>
<pre class="code-block"><code id="requestUriExample"></code></pre>
<p>With body data:</p>
<pre class="code-block"><code id="requestBodyExample"></code></pre>
<p>Let's break it down...</p>
<ul class="collection">
<li class="collection-item">
<p><b><span id="baseUrl"></span></b>
</p>
<p>URL of the authorization endpoint on the server. How is this path constructed will
differ between OAuth providers (such as Keycloak, Okta, etc.).
</p>
</li>
<li class="collection-item">
<p><b><span class="emphasis">response_type</span>=<span id="responseType"></span></b></p>
<p>OAuth 2.0 response type. In this case, we are using the Authorization Code flow, so
we are requesting the authorization <b>code</b>.</p>
</li>
<li class="collection-item">
<p><b><span class="emphasis">client_id</span>=<span id="clientId"></span></b></p>
<p>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.</p>
</li>
<li class="collection-item">
<p><b><span class="emphasis">redirect_uri</span>=<span id="redirectUri"></span></b></p>
<p>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.</p>
</li>
<li class="collection-item">
<p><b><span class="emphasis">scope</span>=<span id="scope"></span></b></p>
<p>Scopes requested by the client. Scopes are used to limit the access of the access
token. In this case, we are requesting the <b>offline_access</b> scope,
which allows the client to obtain a refresh token.</p>
</li>
<li class="collection-item">
<p><b><span class="emphasis">state</span>=<span id="state"></span></b></p>
<p>State parameter. This is an <b>optional parameter</b> 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 (<a href="https://owasp.org/www-community/attacks/csrf" target="_blank">CSRF attack</a>).</p>
</li>
</ul>
<p>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 <b>user</b> with password <b>user</b> for you. After your credentials are successfully verified, you will be redirected back to this playground, to the URL we have specified in the <b>redirect_uri</b> query parameter of the request.</p>
<div class="row flow-submit-container">
<a id="sendRequestBtn" class="waves-effect waves-light btn full-width"
href="#">Authenticate</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section centered">
<a href="/">[ Take me home ]</a>
</div>
</div>
</main>
<footer class="page-footer"></footer>
<script src="../js/load-layout.js"></script>
<script>
function generateSessionState () {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
}
function constructRequestUrl () {
return baseUrl
+ "?" + "response_type=" + responseType
+ "&" + "client_id=" + clientId
+ "&" + "redirect_uri=" + redirectUri
+ "&" + "scope=" + scope
+ "&" + "state=" + state;
}
function fillExample() {
const requestExample = baseUrl + "\n"
+ " ?response_type=" + responseType + "\n"
+ " &client_id=" + clientId + "\n"
+ " &redirect_uri=" + redirectUri + "\n"
+ " &scope=" + scope + "\n"
+ " &state=" + state;
$("#requestUriExample").text(baseUrl);
$("#requestBodyExample").text("client_id=" + clientId);
$("#baseUrl").text(baseUrl);
$("#responseType").text(responseType);
$("#clientId").text(clientId);
$("#redirectUri").text(redirectUri);
$("#scope").text(scope);
$("#state").text(state);
}
function getRedirectUri() {
return window.location.protocol + "//" + window.location.host + "/flow/code-2";
}
const baseUrl = "https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/device";
const responseType = "code";
const clientId = "oauth-playground";
const redirectUri = getRedirectUri();
const scope = "offline_access";
const state = generateSessionState();
fillExample();
$("#sendRequestBtn").attr("href", constructRequestUrl());
</script>
</body>
</html>

View File

@@ -175,7 +175,7 @@
return window.location.protocol + "//" + window.location.host + "/flow/pkce-3"; return window.location.protocol + "//" + window.location.host + "/flow/pkce-3";
} }
const baseUrl = "https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth"; const baseUrl = "https://www.sso.oauth-playground.online/auth";
const responseType = "code"; const responseType = "code";
const clientId = "oauth-playground"; const clientId = "oauth-playground";
const redirectUri = getRedirectUri(); const redirectUri = getRedirectUri();

View File

@@ -115,50 +115,40 @@
<h6>Let's break down what we have received...</h6> <h6>Let's break down what we have received...</h6>
<ul class="collection"> <ul class="collection">
<li class="collection-item"> <li class="collection-item">
<p><b>access_token</b></p> <p><b>token_type</b></p>
<p>This is the actual access token, which allows the client application to access the user's protected resources on the <p>Indicates the type of token issued. In OAuth 2.0, the common type is "Bearer", which means that whoever bears
resource server (e.g., user profile, photos, etc.). the token
It's encoded as a JSON Web Token (JWT), which can be decoded to reveal a header, payload, and signature. can access the resources.</p>
The payload of the JWT contains claims about the user and the authentication event. For example, the iss claim indicates
the issuer of the token, the aud claim specifies the intended audience for the token, and the exp claim specifies the
expiration time of the token. <a href="https://jwt.io/" target="_blank">Want to see what's inside?</a></p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>expires_in</b></p> <p><b>expires_in</b></p>
<p>Indicates the number of seconds for which the <b>access_token</b> is valid. After this time, the access_token will expire and a <p>Indicates the number of seconds for which the <b>access_token</b> is valid. After this time, the access_token
new one must be obtained.</p> will expire and a
new one must be obtained.</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>refresh_expires_in</b></p> <p><b>access_token</b></p>
<p>Indicates the number of seconds for which the refresh_token is valid. Once the refresh token is expired, the client will <p>This is the actual access token, which allows the client application to access the user's protected resources
need to re-authenticate the user to get a new set of tokens.</p> on the
resource server (e.g., user profile, photos, etc.).
</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>refresh_token</b></p> <p><b>refresh_token</b></p>
<p>Used to obtain a new <b>access_token</b> when the current one expires. This allows the client to get a new <b>access_token</b> without <p>Used to obtain a new <b>access_token</b> when the current one expires. This allows the client to get a new
requiring the user to log in again. Like the <b>access_token</b>, it's encoded as a JWT.</p> <b>access_token</b> without
</li> requiring the user to log in again.</p>
<li class="collection-item">
<p><b>token_type</b></p>
<p>Indicates the type of token issued. In OAuth 2.0, the common type is "Bearer", which means that whoever bears the token
can access the resources.</p>
</li>
<li class="collection-item">
<p><b>not-before-policy</b></p>
<p>Specifies a time before which the token should not be accepted. A value of 0 implies the token can be immediately used.</p>
</li>
<li class="collection-item">
<p><b>session_state</b></p>
<p>Represents the state of the user's session at the Authorization Server. This is the same value that could was
returned during the Authorization Code Flow in the <b>session_state</b> parameter.
It can be used in scenarios like OpenID Connect session management to monitor the user's session.</p>
</li> </li>
<li class="collection-item"> <li class="collection-item">
<p><b>scope</b></p> <p><b>scope</b></p>
<p>Specifies the scopes granted by the user to the client application. Scopes determine the permissions associated with the <p>Specifies the scopes granted by the user to the client application. Scopes determine the permissions
<b>access_token</b>. Here, the granted scopes are email, offline_access, and profile. This means that with the provided access_token, the associated with the
client application can access the user's email and profile information and is also granted offline access (typically <b>access_token</b>. Here, the granted scopes are email, offline_access, and profile. This means that with
used in conjunction with refresh tokens).</p> the provided access_token, the
client application can access the user's email and profile information and is also granted offline access
(typically
used in conjunction with refresh tokens).
</p>
</li> </li>
</ul> </ul>
<p>And this concludes the Authorization Code Flow with PKCE. Client application would now be able to request resources on users behalf without having to transfer his credentials with each request.</p> <p>And this concludes the Authorization Code Flow with PKCE. Client application would now be able to request resources on users behalf without having to transfer his credentials with each request.</p>
@@ -176,7 +166,7 @@
<script src="../js/load-layout.js"></script> <script src="../js/load-layout.js"></script>
<script src="../js/cookies.js"></script> <script src="../js/cookies.js"></script>
<script> <script>
const tokenEndpoint = 'https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/token'; const tokenEndpoint = 'https://www.sso.oauth-playground.online/auth/token';
const clientID = 'oauth-playground'; const clientID = 'oauth-playground';
const code = new URLSearchParams(window.location.search).get('code'); const code = new URLSearchParams(window.location.search).get('code');
const codeVerifier = getCookie("code_verifier"); const codeVerifier = getCookie("code_verifier");

View File

@@ -41,7 +41,6 @@
<div class="section"> <div class="section">
<h3 class="header section-header">Flows</h3> <h3 class="header section-header">Flows</h3>
<div class="divider" style="margin-bottom: 10px;"></div> <div class="divider" style="margin-bottom: 10px;"></div>
<div class="row"> <div class="row">
<div class="col s4"> <div class="col s4">
<div class="card horizontal"> <div class="card horizontal">
@@ -56,7 +55,7 @@
protect the client secret.</p> protect the client secret.</p>
</div> </div>
<div class="card-action"> <div class="card-action">
<a href="/flow/code-1">Try it</a> <a href="/flow/code">Try it</a>
</div> </div>
</div> </div>
</div> </div>
@@ -74,7 +73,7 @@
added security against malicious interceptions.</p> added security against malicious interceptions.</p>
</div> </div>
<div class="card-action"> <div class="card-action">
<a href="/flow/pkce-1">Try it</a> <a href="/flow/pkce">Try it</a>
</div> </div>
</div> </div>
</div> </div>
@@ -102,15 +101,18 @@
<div class="card horizontal"> <div class="card horizontal">
<div class="card-stacked flow-card"> <div class="card-stacked flow-card">
<div class="card-content"> <div class="card-content">
<h5>CIBA</h5> <h5>WebAuthN</h5>
<p class="justified">Client Initiated Backchannel Authentication is a protocol extension for OAuth 2.0, tailored for scenarios where <p class="justified">This protocol leverages public key cryptography and allows users to authenticate
the client, such as a financial institution or IoT device, initiates the authentication process without direct user using biometrics, mobile devices, or
interaction on the client's platform. This is useful for "decoupled" authentication experiences, where, for instance, a FIDO security keys, instead of traditional passwords. When a user registers with a website, a unique
user might authenticate on their smartphone when prompted by a smart TV app. In CIBA, once the client requests key pair is
authentication, the authorization server prompts the user on a previously registered device, such as their mobile phone. generated: the private key stays securely on the user's device, and the public key is registered
Upon successful authentication, the authorization server sends a token back to the client. This flow provides a seamless with the website. For
and secure user experience, especially in contexts where traditional OAuth 2.0 interactions might be cumbersome or subsequent logins, the website challenges the user to prove ownership of the private key, typically
impractical.</p> by prompting for a
biometric or a physical action on a security key. WebAuthn enhances user security by reducing
reliance on easily
compromised passwords and defending against phishing attacks.</p>
</div> </div>
<div class="card-action underConstruction"> <div class="card-action underConstruction">
<i class="tiny material-icons">build</i> Under construction <i class="tiny material-icons">build</i> Under construction
@@ -122,13 +124,39 @@
<div class="card horizontal"> <div class="card horizontal">
<div class="card-stacked flow-card"> <div class="card-stacked flow-card">
<div class="card-content"> <div class="card-content">
<h5>WebAuthN</h5> <h5>CIBA</h5>
<p class="justified">This protocol leverages public key cryptography and allows users to authenticate using biometrics, mobile devices, or <p class="justified">Client Initiated Backchannel Authentication is a protocol extension for OAuth 2.0,
FIDO security keys, instead of traditional passwords. When a user registers with a website, a unique key pair is tailored for scenarios where
generated: the private key stays securely on the user's device, and the public key is registered with the website. For the client, such as a financial institution or IoT device, initiates the authentication process
subsequent logins, the website challenges the user to prove ownership of the private key, typically by prompting for a without direct user
biometric or a physical action on a security key. WebAuthn enhances user security by reducing reliance on easily interaction on the client's platform. This is useful for "decoupled" authentication experiences,
compromised passwords and defending against phishing attacks.</p> where, for instance, a
user might authenticate on their smartphone when prompted by a smart TV app. In CIBA, once the
client requests
authentication, the authorization server prompts the user on a previously registered device, such as
their mobile phone.
Upon successful authentication, the authorization server sends a token back to the client. This flow
provides a seamless
and secure user experience, especially in contexts where traditional OAuth 2.0 interactions might be
cumbersome or
impractical.</p>
</div>
<div class="card-action underConstruction">
<i class="tiny material-icons">build</i> Under construction
</div>
</div>
</div>
</div>
<div class="col s4">
<div class="card horizontal">
<div class="card-stacked flow-card">
<div class="card-content">
<h5>Implicit Flow</h5>
<p class="justified">OAuth 2.0 Implicit Flow was designed for browser-based applications where the client cannot maintain the confidentiality
of a secret. In this flow, after user authorization, the authorization server directly redirects the browser to the
client application with an access token in the URL fragment. However, this can expose tokens in browser history or logs,
making it less secure. Consequently, the use of Implicit Flow is being discouraged in favor of the more secure
Authorization Code Flow with PKCE in recent OAuth specifications.</p>
</div> </div>
<div class="card-action underConstruction"> <div class="card-action underConstruction">
<i class="tiny material-icons">build</i> Under construction <i class="tiny material-icons">build</i> Under construction

View File

@@ -3,7 +3,7 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col l6 s12"> <div class="col l6 s12">
<h5 class="white-text">OAuth Playground</h5> <h5 class="white-text">OAuth 2.0 Playground</h5>
<p class="grey-text text-lighten-4">This playground serves as an interactive platform designed to <p class="grey-text text-lighten-4">This playground serves as an interactive platform designed to
familiarize developers and students with the familiarize developers and students with the
intricacies of OAuth authentication processes. Beyond just theoretical knowledge, this playground intricacies of OAuth authentication processes. Beyond just theoretical knowledge, this playground