Content-Length: 684491 | pFad | https://github.com/sebadob/rauthy/commit/3efdcceb2277b2f8b28572485cdd8137115d8b66

50 Merge pull request #111 from sebadob/client-force-mfa-feature · sebadob/rauthy@3efdcce · GitHub
Skip to content

Commit

Permalink
Merge pull request #111 from sebadob/client-force-mfa-feature
Browse files Browse the repository at this point in the history
Client force mfa feature
  • Loading branch information
sebadob authored Oct 28, 2023
2 parents 41b4c9c + 369aae9 commit 3efdcce
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 71 deletions.
5 changes: 3 additions & 2 deletions frontend/src/components/admin/AdminMainPre.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
if (resAdmin.ok) {
sessionInfo = body;
isAdmin = true;
} else if (res.status === 406 ) {
} else if (resAdmin.status === 406 ) {
mfaReqErr = true;
sessionInfo = {};
} else {
Expand Down Expand Up @@ -54,7 +54,8 @@
{:else if !isAdmin}
<div class="noAdmin">
<div class="text">
You are not assigned to the <b>rauthy_admin</b> role and have no access to the admin panel.
You are not assigned to the <b>rauthy_admin</b> role.<br/>
You do not have access to the admin panel.
</div>
<Button on:click={() => window.location.href = '/auth/v1/'}>GO BACK</Button>
</div>
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/admin/ContentWrapper.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class="content"
class:mr={!eventsCollapsed && !eventsWide}
class:mrCollapsed={eventsCollapsed && !eventsWide}
class:mrWide={eventsCollapsed && eventsWide}
class:mrWide={!eventsCollapsed && eventsWide}
in:fade={{delay: tDur * 2, duration: tDur}}
out:fade={{duration: tDur}}
>
Expand All @@ -31,14 +31,14 @@
}
.mr {
margin-right: calc(var(--width-events) - 10px);
margin-right: var(--width-events);
}
.mrCollapsed {
margin-right: calc(var(--width-events-collapsed) - 10px);
margin-right: var(--width-events-collapsed);
}
.mrWide {
margin-right: calc(var(--width-events-wide) - 10px);
margin-right: var(--width-events-wide);
}
</style>
35 changes: 34 additions & 1 deletion frontend/src/components/admin/clients/ClientConfig.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import {putClient} from "../../../utils/dataFetchingAdmin.js";
import Input from "$lib/inputs/Input.svelte";
import ExpandableInput from "$lib/expandableInputs/ExpandableInputs.svelte";
import {slide} from "svelte/transition";
export let client = {};
export let onSave;
Expand Down Expand Up @@ -57,7 +58,7 @@
client.post_logout_redirect_uris = [];
}
if (!client.name) {
client.name = '';
client.name = '';
}
return () => clearTimeout(timer);
});
Expand Down Expand Up @@ -198,6 +199,34 @@
</div>
</div>
<!-- Force MFA -->
<div class="unit">
<div class="label font-label">
FORCE MFA
</div>
<div class="value">
<Switch bind:selected={client.force_mfa}/>
</div>
</div>
{#if client.id === 'rauthy'}
<div class="desc" style:margin="-10px 0 -15px 5px">
<p>
<span style:color="var(--col-err)"><b>CAUTION:</b></span>
The <code>FORCE MFA</code> option for <code>rauthy</code> itself is managed statically via the
<code>ADMIN_FORCE_MFA</code> config variable and will be overridden with each restart.
</p>
</div>
{:else if client.force_mfa}
<div transition:slide class="desc" style:margin="-10px 0 -15px 5px">
<p>
<span style:color="var(--col-err)"><b>CAUTION:</b></span>
If you <code>FORCE MFA</code> for this client here, this will only apply to the
<code>authorization_code</code> flow! If you use other flows,
MFA cannot be forced for them!
</p>
</div>
{/if}
<!-- Scopes Description -->
<div class="separator"></div>
<div class="desc">
Expand Down Expand Up @@ -412,6 +441,10 @@
</div>
<style>
code {
font-size: .95rem;
}
.challenges {
width: 140px;
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/admin/events/Events.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
display: flex;
flex-direction: column;
justify-content: space-between;
background: var(--col-bg);
box-shadow: -2px 0 5px var(--col-gmid);
transition: all 250ms ease-in-out;
}
Expand Down
118 changes: 68 additions & 50 deletions frontend/src/routes/oidc/authorize/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
let err = '';
let isReady = false;
let needsPassword = false;
let clientMfaForce = false;
let showReset = false;
let showResetRequest = false;
let emailSuccess = false;
Expand Down Expand Up @@ -171,11 +172,18 @@
async function handleAuthRes(res) {
if (res.status === 202) {
// -> all good
window.location.replace(res.headers.get('location'));
} else if (res.status === 200) {
// -> all good, but needs additional passkey validation
err = '';
webauthnData = await res.json();
} else if (res.status === 406) {
// 406 -> client forces MFA while the user has none
err = t.clientForceMfa;
clientMfaForce = true;
} else if (res.status === 429) {
// 429 -> too many failed logins
let notBefore = Number.parseInt(res.headers.get('x-retry-not-before'));
let nbfDate = formatDateFromTs(notBefore);
let diff = notBefore * 1000 - new Date().getTime();
Expand Down Expand Up @@ -284,61 +292,63 @@
/>
{/if}
<Input
type="email"
name="rauthyEmail"
bind:value={formValues.email}
bind:error={formErrors.email}
autocomplete="email"
placeholder={t.email}
disabled={tooManyRequests}
on:enter={onSubmit}
on:input={onEmailInput}
>
{t.email?.toUpperCase()}
</Input>
{#if needsPassword && existingMfaUser !== formValues.email && !showReset}
<PasswordInput
bind:bindThis={passwordInput}
name="rauthyPassword"
bind:value={formValues.password}
bind:error={formErrors.password}
autocomplete="current-password"
placeholder={t.password}
disabled={tooManyRequests}
{#if !clientMfaForce}
<Input
type="email"
name="rauthyEmail"
bind:value={formValues.email}
bind:error={formErrors.email}
autocomplete="email"
placeholder={t.email}
disabled={tooManyRequests || clientMfaForce}
on:enter={onSubmit}
on:input={onEmailInput}
>
{t.password?.toUpperCase()}
</PasswordInput>
{#if showResetRequest && !tooManyRequests}
<div
role="button"
tabindex="0"
class="forgotten"
transition:scale|global
on:click={handleShowReset}
on:keypress={handleShowReset}
{t.email?.toUpperCase()}
</Input>
{#if needsPassword && existingMfaUser !== formValues.email && !showReset}
<PasswordInput
bind:bindThis={passwordInput}
name="rauthyPassword"
bind:value={formValues.password}
bind:error={formErrors.password}
autocomplete="current-password"
placeholder={t.password}
disabled={tooManyRequests || clientMfaForce}
on:enter={onSubmit}
>
{t.passwordForgotten}
</div>
{t.password?.toUpperCase()}
</PasswordInput>
{#if showResetRequest && !tooManyRequests}
<div
role="button"
tabindex="0"
class="forgotten"
transition:scale|global
on:click={handleShowReset}
on:keypress={handleShowReset}
>
{t.passwordForgotten}
</div>
{/if}
{/if}
{/if}
{#if !tooManyRequests}
{#if showReset}
<div class="btn">
<Button on:click={requestReset}>
{t.passwordRequest?.toUpperCase()}
</Button>
</div>
{:else}
<div class="btn">
<Button on:click={onSubmit} bind:isLoading>
{t.login?.toUpperCase()}
</Button>
</div>
{#if !tooManyRequests && !clientMfaForce}
{#if showReset}
<div class="btn">
<Button on:click={requestReset}>
{t.passwordRequest?.toUpperCase()}
</Button>
</div>
{:else}
<div class="btn">
<Button on:click={onSubmit} bind:isLoading>
{t.login?.toUpperCase()}
</Button>
</div>
{/if}
{/if}
{/if}
Expand All @@ -353,6 +363,14 @@
{t.emailSentMsg}
</div>
{/if}
{#if clientMfaForce}
<div class="btn">
<Button on:click={() => window.location.href = '/auth/v1/account'}>
ACCOUNT LOGIN
</Button>
</div>
{/if}
</div>
<LangSelector absolute/>
Expand Down
5 changes: 5 additions & 0 deletions migrations/postgres/12_clients_force_mfa.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alter table clients
add force_mfa bool default false not null;

alter table clients
alter column force_mfa drop default;
67 changes: 67 additions & 0 deletions migrations/sqlite/12_clients_force_mfa.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
alter table clients
rename to clients_old;

create table clients
(
id varchar not null
constraint clients_pk
primary key,
name varchar,
enabled bool not null,
confidential bool not null,
secret blob,
secret_kid varchar,
redirect_uris varchar not null,
post_logout_redirect_uris varchar,
allowed_origens varchar,
flows_enabled varchar not null,
access_token_alg varchar not null,
id_token_alg varchar not null,
refresh_token bool not null,
auth_code_lifetime integer not null,
access_token_lifetime integer not null,
scopes varchar not null,
default_scopes varchar not null,
challenge varchar,
force_mfa bool not null
);

insert into clients(id,
name,
enabled,
confidential,
secret,
secret_kid,
redirect_uris,
post_logout_redirect_uris,
allowed_origens,
flows_enabled,
access_token_alg,
id_token_alg,
refresh_token,
auth_code_lifetime,
access_token_lifetime,
scopes,
default_scopes,
challenge,
force_mfa)
select id,
name,
enabled,
confidential,
secret,
secret_kid,
redirect_uris,
post_logout_redirect_uris,
allowed_origens,
flows_enabled,
access_token_alg,
id_token_alg,
refresh_token,
auth_code_lifetime,
access_token_lifetime,
scopes,
default_scopes,
challenge,
false as force_mfa
from clients_old;
1 change: 1 addition & 0 deletions rauthy-main/tests/handler_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ async fn test_authorization_code_flow() -> Result<(), Box<dyn Error>> {
],
default_scopes: vec!["openid".to_string(), "email".to_string()],
challenges: None,
force_mfa: false,
};
let url_client = format!("{}/clients/{}", backend_url, CLIENT_ID);
let auth_headers = get_auth_headers().await?;
Expand Down
1 change: 1 addition & 0 deletions rauthy-main/tests/xxx_handler_cust_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ async fn test_cust_attrs() -> Result<(), Box<dyn Error>> {
scopes,
default_scopes,
challenges: c.challenges,
force_mfa: c.force_mfa,
};
let res = client
.put(&url_client)
Expand Down
1 change: 1 addition & 0 deletions rauthy-main/tests/zzz_handler_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ async fn test_clients() -> Result<(), Box<dyn Error>> {
"doestnotexist".to_string(),
],
challenges: Some(vec!["S256".to_string(), "plain".to_string()]),
force_mfa: false,
};

let url_id = format!("{}/clients/{}", backend_url, client.id);
Expand Down
Loading

0 comments on commit 3efdcce

Please sign in to comment.








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://github.com/sebadob/rauthy/commit/3efdcceb2277b2f8b28572485cdd8137115d8b66

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy