mirror of
https://github.com/ysoftdevs/oauth-playground-client.git
synced 2026-01-11 22:41:29 +01:00
First impl of code flow
This commit is contained in:
@@ -142,20 +142,33 @@ body {
|
||||
border-radius: 5px;
|
||||
/* rounded corners */
|
||||
padding: 20px;
|
||||
/* space inside the block */
|
||||
overflow-x: auto;
|
||||
/* allow horizontal scrolling if code is too wide */
|
||||
}
|
||||
|
||||
.code-block code {
|
||||
color: #333;
|
||||
/* dark text color for code */
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
/* monospace font */
|
||||
white-space: pre;
|
||||
/* keep whitespace as is */
|
||||
}
|
||||
|
||||
.emphasis {
|
||||
color: #FF6600;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
/* CSS3 */
|
||||
white-space: -moz-pre-wrap;
|
||||
/* Firefox */
|
||||
white-space: -pre-wrap;
|
||||
/* Opera <7 */
|
||||
white-space: -o-pre-wrap;
|
||||
/* Opera 7+ */
|
||||
word-wrap: break-word;
|
||||
/* IE */
|
||||
overflow-wrap: break-word;
|
||||
/* CSS3 */
|
||||
}
|
||||
|
||||
.card-stacked {
|
||||
width: 100%;
|
||||
}
|
||||
171
src/flow/code-1.html
Normal file
171
src/flow/code-1.html
Normal file
@@ -0,0 +1,171 @@
|
||||
<!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</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" style="text-align: center;">Authorization Code Flow</h3>
|
||||
<div class="circle-container">
|
||||
<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">
|
||||
Build the authorization URL and redirect the user to the authorization server
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
After the user is redirected back to the client, verify the state matches
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
Exchange the authorization code for an access token
|
||||
</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. Build the Authorization URL</h6>
|
||||
|
||||
<pre class="code-block"><code><span id="baseUrl"></span>?
|
||||
&<span id="responseType"></span>
|
||||
&<span id="clientId"></span>
|
||||
&<span id="redirectUri"></span>
|
||||
&<span id="scope"></span>
|
||||
&<span id="state"></span></code></pre>
|
||||
<h6>Let's break it down...</h6>
|
||||
<ul class="collection">
|
||||
<li class="collection-item">
|
||||
<p><b><span id="baseUrlExpl"></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 or Okta). to
|
||||
find out the proper URL, there always exists
|
||||
<b>/.well-known/openid-configuration</b> endpoint that contains all the necessary
|
||||
information.
|
||||
</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">response_type</span>=<span id="responseTypeExpl"></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 code.</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">client_id</span>=<span id="clientIdExpl"></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="redirectUriExpl"></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="scopeExpl"></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 offline_access 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="stateExpl"></span></b></p>
|
||||
<p>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.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="row" style="text-align: center; margin-top: 25px;">
|
||||
<a id="sendRequestBtn" style="width: 20%" class="waves-effect waves-light btn"
|
||||
href="#">Send request</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="page-footer"></footer>
|
||||
<script>
|
||||
$(".page-footer").load("../layout/footer.html");
|
||||
$("#page-header").load("../layout/header.html");
|
||||
|
||||
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 generateSessionState () {
|
||||
const sessionState = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||
setCookie("sessionState", sessionState, 15);
|
||||
return sessionState;
|
||||
}
|
||||
|
||||
function constructRequestUrl () {
|
||||
return baseUrl
|
||||
+ "?" + "response_type=" + responseType
|
||||
+ "&" + "client_id=" + clientId
|
||||
+ "&" + "redirect_uri=" + redirectUri
|
||||
+ "&" + "scope=" + scope
|
||||
+ "&" + "state=" + state;
|
||||
}
|
||||
|
||||
const baseUrl = "https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth";
|
||||
const responseType = "code";
|
||||
const clientId = "oauth-playground";
|
||||
const redirectUri = "http://localhost:5555/flow/code-2";
|
||||
const scope = "offline_access";
|
||||
const state = generateSessionState();
|
||||
|
||||
$("#sendRequestBtn").attr("href", constructRequestUrl());
|
||||
|
||||
$("#baseUrl").text(baseUrl);
|
||||
$("#baseUrlExpl").text(baseUrl);
|
||||
$("#responseType").text("response_type=" + responseType);
|
||||
$("#responseTypeExpl").text(responseType);
|
||||
$("#clientId").text("client_id=" + clientId);
|
||||
$("#clientIdExpl").text(clientId);
|
||||
$("#redirectUri").text("redirect_uri=" + redirectUri);
|
||||
$("#redirectUriExpl").text(redirectUri);
|
||||
$("#scope").text("scope=" + scope);
|
||||
$("#scopeExpl").text(scope);
|
||||
$("#state").text("state=" + state);
|
||||
$("#stateExpl").text(state);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
111
src/flow/code-2.html
Normal file
111
src/flow/code-2.html
Normal file
@@ -0,0 +1,111 @@
|
||||
<!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</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" style="text-align: center;">Authorization Code Flow</h3>
|
||||
<div class="circle-container">
|
||||
<div class="circle">
|
||||
1
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="circle">
|
||||
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">
|
||||
Build the authorization URL and redirect the user to the authorization server
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
After the user is redirected back to the client, verify the state matches
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
Exchange the authorization code for an access token
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="col s12 m7">
|
||||
<div class="card horizontal">
|
||||
<div class="card-stacked">
|
||||
<div class="card-content">
|
||||
<h6>2. Verify the state parameter</h6>
|
||||
|
||||
<p>You have now been redirected back to the application, to the page that was specified in the <b>redirect-url</b> parameter. In the URL you can notice, that there are addtional query parameters:</p>
|
||||
<pre class="code-block"><code id="queryParams"></code></pre>
|
||||
<h6>Let's break it down...</h6>
|
||||
<ul class="collection">
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">state</span>=<span id="state"></span></b></p>
|
||||
<p>This is the state parameter that was sent in the initial request. It is used to prevent CSRF attacks.</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">session_state</span>=<span id="sessionState"></span></b></p>
|
||||
<p>Session state is a parameter that is used to maintain state between the request and callback. It is used to prevent CSRF attacks.</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">code</span>=<span id="code"></span></b></p>
|
||||
<p>This is the authorization code that will be exchanged for an access token.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>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?</p>
|
||||
|
||||
<div class="row" style="text-align: center; margin-top: 25px;">
|
||||
<a style="width: 20%" class="waves-effect waves-light btn"
|
||||
onclick="proceedToNextStep()">States are matching</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="page-footer"></footer>
|
||||
<script>
|
||||
$(".page-footer").load("../layout/footer.html");
|
||||
$("#page-header").load("../layout/header.html");
|
||||
|
||||
$("#queryParams").text(window.location.search)
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const code = urlParams.get('code');
|
||||
const state = urlParams.get('state');
|
||||
const sessionState = urlParams.get('session_state');
|
||||
|
||||
$("#state").text(state);
|
||||
$("#sessionState").text(sessionState);
|
||||
$("#code").text(code);
|
||||
|
||||
function proceedToNextStep() {
|
||||
window.location.href = "/flow/code-3" + window.location.search;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
150
src/flow/code-3.html
Normal file
150
src/flow/code-3.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<!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</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" style="text-align: center;">Authorization Code Flow</h3>
|
||||
<div class="circle-container">
|
||||
<div class="circle">
|
||||
1
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="circle">
|
||||
2
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="circle">
|
||||
3
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col s4 circle-text">
|
||||
Build the authorization URL and redirect the user to the authorization server
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
After the user is redirected back to the client, verify the state matches
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
Exchange the authorization code for an access token
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="col s12 m7">
|
||||
<div class="card horizontal">
|
||||
<div class="card-stacked">
|
||||
<div class="card-content">
|
||||
<h6>3. Exchange the code for token</h6>
|
||||
|
||||
<pre class="code-block"><code id="requestExample"></code></pre>
|
||||
<h6>Let's break it down, line by line...</h6>
|
||||
<ul class="collection">
|
||||
<li class="collection-item">
|
||||
<p><b>https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/token</b>
|
||||
</p>
|
||||
<p>The token endpoint URL</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">grant_type</span>=authorization_code</b></p>
|
||||
<p>The grant type, in this case <b>authorization_code</b></p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">client_id</span>=oauth-playground</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>=http://localhost:5555/flow/code-2</b></p>
|
||||
<p>The redirect URI</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">code</span>=--Vto71vecBQbZnbA7ErehWHVQq4x1pm5YtA9Rr7x5zjhMGS</b></p>
|
||||
<p>This is the authorization code we got in the previous step and is used to obtain the
|
||||
access token.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="row" style="text-align: center; margin-top: 25px;">
|
||||
<a style="width: 20%" class="waves-effect waves-light btn"
|
||||
onClick="getToken()">Get token</a>
|
||||
</div>
|
||||
|
||||
<pre class="code-block"><code id="token"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="page-footer"></footer>
|
||||
<script>
|
||||
$(".page-footer").load("../layout/footer.html");
|
||||
$("#page-header").load("../layout/header.html");
|
||||
|
||||
function fillRequestExample() {
|
||||
const requestExample =
|
||||
"POST https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/token?" + "\n\n"
|
||||
+ "grant_type=authorization_code" + "\n"
|
||||
+ "&client_id=oauth-playground" + "\n"
|
||||
+ "&redirect_uri=http://localhost:5555/flow/code-2" + "\n"
|
||||
+ "&code=--Vto71vecBQbZnbA7ErehWHVQq4x1pm5YtA9Rr7x5zjhMGS";
|
||||
|
||||
$("#requestExample").text(requestExample);
|
||||
}
|
||||
|
||||
function getToken() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const code = urlParams.get('code');
|
||||
|
||||
const tokenEndpoint = 'https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/token';
|
||||
const clientID = 'oauth-playground';
|
||||
const redirectURI = 'http://localhost:5555/flow/code-2';
|
||||
|
||||
const bodyData = new URLSearchParams();
|
||||
bodyData.append('grant_type', 'authorization_code');
|
||||
bodyData.append('client_id', clientID);
|
||||
bodyData.append('redirect_uri', redirectURI);
|
||||
bodyData.append('code', code);
|
||||
|
||||
fetch(tokenEndpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: bodyData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data); // This will print the access token if the request was successful
|
||||
$("#token").text(JSON.stringify(data, null, 2));
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching the token:', error);
|
||||
});
|
||||
}
|
||||
|
||||
fillRequestExample();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,31 +12,23 @@
|
||||
<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>
|
||||
<nav>
|
||||
<div class="nav-wrapper">
|
||||
<a href="/" class="brand-logo center">
|
||||
OAuth 2.0 Playground
|
||||
<span style="font-size: 15px; color:#FF6600; font-weight:bold;">by Y Soft</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<header id="page-header">
|
||||
</header>
|
||||
<main>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h3 class="header" style="text-align: center;">Lorem Ipsum</h3>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
|
||||
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
|
||||
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
||||
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis
|
||||
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
|
||||
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<h3 class="header" style="text-align: center;">Welcome to OAuth 2.0 Playground</h3>
|
||||
<p>This playground serves as an interactive platform designed to familiarize developers and students with the
|
||||
intricacies of OAuth authentication processes. Beyond just theoretical knowledge, this playground provides practical
|
||||
insights into the OAuth token exchange,
|
||||
callback handling, and potential pitfalls or challenges one might face during real-world integrations. The ultimate aim
|
||||
is to bolster
|
||||
understanding and confidence in implementing OAuth, ensuring secure and efficient user authentication and authorization
|
||||
in modern web applications.</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
@@ -57,7 +49,7 @@
|
||||
protect the client secret.</p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a onclick="loadAuthorizationCodeFlowPage()">Try it</a>
|
||||
<a href="/flow/code-1">Try it</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,7 +68,7 @@
|
||||
resources without the need for intricate user interactions.</p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a onclick="loadDeviceAuthorizationGrantPage()">Try it</a>
|
||||
<!--<a onclick="loadWebAuthNPage()">Try it</a>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,7 +86,7 @@
|
||||
compromised passwords and defending against phishing attacks.</p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a onclick="loadWebAuthNPage()">Try it</a>
|
||||
<!--<a onclick="loadWebAuthNPage()">Try it</a>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,50 +95,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="page-footer">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col l6 s12">
|
||||
<h5 class="white-text">OAuth Playground</h5>
|
||||
<p class="grey-text text-lighten-4">This playground serves as an interactive platform designed to familiarize developers and students with the
|
||||
intricacies of OAuth authentication processes. Beyond just theoretical knowledge, this playground provides practical insights into the OAuth token exchange,
|
||||
callback handling, and potential pitfalls or challenges one might face during real-world integrations. The ultimate aim is to bolster
|
||||
understanding and confidence in implementing OAuth, ensuring secure and efficient user authentication and authorization
|
||||
in modern web applications.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col l4 offset-l2 s12">
|
||||
<h5 class="white-text">Links</h5>
|
||||
<ul>
|
||||
<li><a class="grey-text text-lighten-3" href="https://www.oauth.com/" target="_blank">OAuth 2.0 Simplified</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="#!">Link 2</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="https://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth Wikipedia</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="https://www.ietf.org/rfc/rfc6749.txt" target="_blank">OAuth 2.0 RFC</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<div class="container">
|
||||
© 2023 Y Soft Corporation
|
||||
<a class="grey-text text-lighten-4 right" style="color:#FF6600 !important; font-weight:bold;" href="https://www.daretothinkbyg.com" target="_blank">Join us today!</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<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>
|
||||
<footer class="page-footer"></footer>
|
||||
<script>
|
||||
function loadAuthorizationCodeFlowPage() {
|
||||
$("main").load("pages/authorization-code-flow.html");
|
||||
}
|
||||
|
||||
function loadDeviceAuthorizationGrantPage() {
|
||||
$("main").load("pages/device-authorization-grant.html");
|
||||
}
|
||||
|
||||
function loadWebAuthNPage() {
|
||||
$("main").load("pages/webauthn.html");
|
||||
}
|
||||
$(".page-footer").load("layout/footer.html");
|
||||
$("#page-header").load("layout/header.html");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
36
src/layout/footer.html
Normal file
36
src/layout/footer.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col l6 s12">
|
||||
<h5 class="white-text">OAuth Playground</h5>
|
||||
<p class="grey-text text-lighten-4">This playground serves as an interactive platform designed to
|
||||
familiarize developers and students with the
|
||||
intricacies of OAuth authentication processes. Beyond just theoretical knowledge, this playground
|
||||
provides practical insights into the OAuth token exchange,
|
||||
callback handling, and potential pitfalls or challenges one might face during real-world
|
||||
integrations. The ultimate aim is to bolster
|
||||
understanding and confidence in implementing OAuth, ensuring secure and efficient user
|
||||
authentication and authorization
|
||||
in modern web applications.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col l4 offset-l2 s12">
|
||||
<h5 class="white-text">Links</h5>
|
||||
<ul>
|
||||
<li><a class="grey-text text-lighten-3" href="https://www.oauth.com/" target="_blank">OAuth 2.0
|
||||
Simplified</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="#!">Link 2</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="https://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth
|
||||
Wikipedia</a></li>
|
||||
<li><a class="grey-text text-lighten-3" href="https://www.ietf.org/rfc/rfc6749.txt"
|
||||
target="_blank">OAuth 2.0 RFC</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<div class="container">
|
||||
© 2023 Y Soft Corporation
|
||||
<a class="grey-text text-lighten-4 right" style="color:#FF6600 !important; font-weight:bold;"
|
||||
href="https://www.daretothinkbyg.com" target="_blank">Join us today!</a>
|
||||
</div>
|
||||
</div>
|
||||
8
src/layout/header.html
Normal file
8
src/layout/header.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<nav>
|
||||
<div class="nav-wrapper">
|
||||
<a href="/" class="brand-logo center">
|
||||
OAuth 2.0 Playground
|
||||
<span style="font-size: 15px; color:#FF6600; font-weight:bold;">by Y Soft</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -1,93 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h3 class="header" style="text-align: center;">Authorization Code Flow</h3>
|
||||
<div class="circle-container">
|
||||
<!-- First Circle -->
|
||||
<div class="circle">
|
||||
1
|
||||
</div>
|
||||
<!-- Line connecting first and second circle -->
|
||||
<div class="line line-inactive"></div>
|
||||
<!-- Second Circle -->
|
||||
<div class="circle circle-inactive">
|
||||
2
|
||||
</div>
|
||||
<!-- Line connecting second and third circle -->
|
||||
<div class="line line-inactive"></div>
|
||||
<!-- Third Circle -->
|
||||
<div class="circle circle-inactive">
|
||||
3
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Texts under the circles -->
|
||||
<div class="row">
|
||||
<div class="col s4 circle-text">
|
||||
Build the authorization URL and redirect the user to the authorization server
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
After the user is redirected back to the client, verify the state matches
|
||||
</div>
|
||||
<div class="col s4 circle-text">
|
||||
Exchange the authorization code for an access token
|
||||
</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. Build the Authorization URL</h6>
|
||||
|
||||
<pre class="code-block"><code>https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth?
|
||||
response_type=code
|
||||
&client_id=oauth-playground
|
||||
&redirect_uri=http://localhost:5555/
|
||||
&scope=offline_access
|
||||
&state=9igSQpeGo2ua52bU
|
||||
</code></pre>
|
||||
<h6>Let's break it down, line by line...</h6>
|
||||
<ul class="collection">
|
||||
<li class="collection-item">
|
||||
<p><b>https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth?</b></p>
|
||||
<p>URL of the authorization endpoint on the server. How is this path constructed will differ between OAuth providers (such as Keycloak or Okta). to
|
||||
find out the proper URL, there always exists <b>/.well-known/openid-configuration</b> endpoint that contains all the necessary information.
|
||||
</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">response_type</span>=code</b></p>
|
||||
<p>OAuth 2.0 response type. In this case, we are using the Authorization Code flow, so we are requesting the authorization code.</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">client_id</span>=oauth-playground</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>=http://localhost:5555/</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>=offline_access</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 offline_access scope,
|
||||
which allows the client to obtain a refresh token.</p>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p><b><span class="emphasis">state</span>=9igSQpeGo2ua52bU</b></p>
|
||||
<p>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.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="row" style="text-align: center; margin-top: 25px;">
|
||||
<a style="width: 20%" class="waves-effect waves-light btn"
|
||||
href="https://sso.rumbuddy.cz/realms/OAuthPlayground/protocol/openid-connect/auth?response_type=code&client_id=oauth-playground&redirect_uri=http://localhost:5555/&scope=offline_access">Send request</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1 +0,0 @@
|
||||
Device Authorization Grant
|
||||
@@ -1 +0,0 @@
|
||||
WebAuthN
|
||||
Reference in New Issue
Block a user