Skip to content

Commit

Permalink
Apps: Add example for step-up authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasdarimont committed Oct 19, 2023
1 parent 3f29292 commit 55f1b8f
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 7 deletions.
33 changes: 26 additions & 7 deletions apps/acme-account-console/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ <h1>ClientId: <span id="clientInfo"></span></h1>
<button name="securityBtn" onclick="showSecurity()" class="security">Security</button>
<button name="appsBtn" onclick="showApps()" class="apps">Apps</button>
<button name="reauthBtn" onclick="enforceCurrentAuth()" class="reauth">ReAuth</button>
<button name="stepupBtn" onclick="showStepUp()" class="stepup">Stepup</button>
<button name="switchContextBtn" onclick="switchContext()" class="switchContext">Switch Context</button>
<button name="accountBtn" onclick="keycloak.accountManagement()" class="account">Account</button>
<button name="logoutBtn" onclick="keycloak.logout()" class="logout">Logout</button>
Expand All @@ -167,7 +168,7 @@ <h1>ClientId: <span id="clientInfo"></span></h1>

// ?scope=openid+email+custom.profile+custom.ageinfo
//let scope = searchParams.get("scope") || 'openid email acme.profile acme.ageinfo';
let scope = searchParams.get("scope") || 'openid email acme.profile';
let scope = searchParams.get("scope") || 'openid email';
// &show=profile,settings,apps,security,logout
// &show=profile,settings,apps,security,logout,token,idToken,userinfo
// &show=profile,logout,token,idToken,userinfo,reauth,account
Expand Down Expand Up @@ -229,8 +230,8 @@ <h1>ClientId: <span id="clientInfo"></span></h1>

};

const allContextClasses = ["profile", "account", "settings", "meinfo", "token", "idToken", "userinfo", "security", "apps", "reauth", "logout", "deleteAccount", "switchContext", "revoke"];
const contextClassesToHideDefault = ["meinfo", "token", "idToken", "userinfo", "reauth", "account", "deleteAccount", "switchContext", "revoke"];
const allContextClasses = ["profile", "account", "settings", "meinfo", "token", "idToken", "userinfo", "security", "apps", "reauth", "logout", "deleteAccount", "switchContext", "revoke", "stepup"];
const contextClassesToHideDefault = ["meinfo", "token", "idToken", "userinfo", "reauth", "account", "deleteAccount", "switchContext", "revoke", "stepup"];
const contextClassesToShowDefault = [...allContextClasses].filter((value, index, arr) => {
return !contextClassesToHideDefault.includes(value);
});
Expand Down Expand Up @@ -264,7 +265,7 @@ <h1>ClientId: <span id="clientInfo"></span></h1>

// workaround for changes with oidc logout in Keycloak 18.0.0
// See https://www.keycloak.org/docs/latest/upgrading/index.html#openid-connect-logout
keycloak.createLogoutUrl = function(options) {
keycloak.createLogoutUrl = function (options) {
return keycloak.endpoints.logout()
+ '?id_token_hint=' + keycloak.idToken
+ '&post_logout_redirect_uri=' + encodeURIComponent(window.location.href);
Expand Down Expand Up @@ -500,6 +501,24 @@ <h1>ClientId: <span id="clientInfo"></span></h1>
show(securityHtml, "message-content");
}

async function showStepUp() {

let stepupHtml = `
<button onclick="stepUpAuth()">Stepup MFA</button>
`;

show(stepupHtml, "message-content");
}

function stepUpAuth() {
keycloak.login({
acr: {
values: ["2fa"],
essential: true
}
});
}

async function showApps() {

await keycloak.updateToken(5);
Expand Down Expand Up @@ -666,7 +685,7 @@ <h1>ClientId: <span id="clientInfo"></span></h1>
// use phoneNumber from IDToken directly
let phoneNumber = escapeHtml(keycloak.idTokenParsed['phone_number']);
let phoneNumberVerified = keycloak.idTokenParsed['phone_number_verified']
if (!phoneNumber){
if (!phoneNumber) {
phoneNumber = "N/A";
phoneNumberVerified = false;
}
Expand Down Expand Up @@ -696,14 +715,14 @@ <h1>ClientId: <span id="clientInfo"></span></h1>
<tr>
<td class="label">Email</td>
<td><span id="email">${email}</span></td>
<td title="${ emailVerified ? 'Email verified' : ''}">${ emailVerified ? '&#10004;' : ''}</td>
<td title="${emailVerified ? 'Email verified' : ''}">${emailVerified ? '&#10004;' : ''}</td>
<td><a id="changeEmail" href="#" onclick="changeEmail();return false">Update</a></td>
<td></td>
</tr>
<tr>
<td class="label">Phone</td>
<td><span id="phoneNumber">${phoneNumber}</span></td>
<td title="${ phoneNumberVerified ? 'Phone number verified' : ''}">${ phoneNumberVerified ? '&#10004;' : ''}</td>
<td title="${phoneNumberVerified ? 'Phone number verified' : ''}">${phoneNumberVerified ? '&#10004;' : ''}</td>
<td></td>
<td></td>
</tr>
Expand Down
126 changes: 126 additions & 0 deletions config/stage/dev/realms/acme-stepup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
realm: acme-stepup
displayName: "Acme Step-up"
enabled: true

browserFlow: "Browser Step-Up"

attributes:
"acr.loa.map": "{\"cookie\":\"0\",\"pw\":\"1\",\"2fa\":\"2\"}"

clients:
- clientId: app-minispa
protocol: openid-connect
name: Acme Account Console
description: "Acme Account Console Description"
enabled: true
publicClient: true
standardFlowEnabled: true
directAccessGrantsEnabled: false
# Show client in account-console
alwaysDisplayInConsole: true
serviceAccountsEnabled: false
# attributes: { }
fullScopeAllowed: true
rootUrl: "$(env:APPS_FRONTEND_URL_MINISPA)"
baseUrl: "/?realm=acme-stepup&show=profile,apps,security,token,idToken,stepup,reauth,logout"
adminUrl: ""
redirectUris:
- "/*"
webOrigins:
- "+"
defaultClientScopes:
- "email"
- "roles"
- "profile"
- "acr"
optionalClientScopes:
- "phone"
attributes:
"pkce.code.challenge.method": "S256"
"post.logout.redirect.uris": "+"

authenticationFlows:
- alias: "Browser Step-Up"
description: "This flow implements a custom browser pattern"
providerId: basic-flow
builtIn: false
topLevel: true
authenticationExecutions:
- authenticator: auth-cookie
requirement: ALTERNATIVE
- flowAlias: "Identity Forms"
requirement: ALTERNATIVE
autheticatorFlow: true

- alias: "Identity Forms"
description: "Sub-Flow to ask user for username an password"
providerId: basic-flow
topLevel: false
builtIn: false
authenticationExecutions:

- flowAlias: "Password Condition"
requirement: CONDITIONAL
autheticatorFlow: true
- flowAlias: "2FA Condition"
requirement: CONDITIONAL
autheticatorFlow: true

- alias: "Password Condition"
description: "Sub-Flow to ask user for username / password"
providerId: basic-flow
topLevel: false
builtIn: false
authenticationExecutions:
- authenticator: conditional-level-of-authentication
requirement: REQUIRED
authenticatorConfig: "username-password"
- authenticator: auth-username-password-form
requirement: REQUIRED

- alias: "2FA Condition"
description: "Sub-Flow to ask user for 2FA during stepup"
providerId: basic-flow
topLevel: false
builtIn: false
authenticationExecutions:
- authenticator: conditional-user-configured
requirement: REQUIRED
- authenticator: conditional-level-of-authentication
requirement: REQUIRED
authenticatorConfig: "2fa-stepup"
- authenticator: acme-auth-otp-form
requirement: ALTERNATIVE
- authenticator: auth-recovery-authn-code-form
requirement: ALTERNATIVE

authenticatorConfig:
- alias: "username-password"
config:
"loa-condition-level": "1"
"loa-max-age": "36000"
- alias: "2fa-stepup"
config:
"loa-condition-level": "2"
"loa-max-age": "300"

users:
- username: tester
email: tester@local
firstName: Theo
lastName: Tester
enabled: true
emailVerified: true
attributes:
locale: [ "en" ]
phoneNumber: [ "+49178111222333" ]
phoneNumberVerified: [ "true" ]
title: [ "" ]
salutation: [ "mr" ]
# Thomas
picture: [ "https://en.gravatar.com/userimage/52342809/a957ac868585f91edf7eb9b7463328b9.jpeg?size=64" ]
credentials:
- type: password
userLabel: initial
value: test
temporary: false

0 comments on commit 55f1b8f

Please sign in to comment.