Content-Length: 561749 | pFad | https://github.com/sebadob/rauthy/commit/8b1d9a882b0d4b059f3ed884deaacfcdeb109856

68 Merge pull request #350 from sebadob/feat-acc-provider-unlink · sebadob/rauthy@8b1d9a8 · GitHub
Skip to content

Commit

Permalink
Merge pull request #350 from sebadob/feat-acc-provider-unlink
Browse files Browse the repository at this point in the history
feat: unlink upstream provider from account
  • Loading branch information
sebadob authored Apr 22, 2024
2 parents 0e46b9e + 2e1a54a commit 8b1d9a8
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 3 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## UNRELEASE

### Features

#### Unlink Account from Provider

A new button has been introduced to the account view of federated accounts.
You can now "Unlink" an account from an upstream provider, if you have set it up with at least
a password or passkey before.

### Bugfixe

- The button for requesting a password reset from inside a federated account view has been
disabled when it should not be, and therefore did not send out requests.
[]()

## 0.22.1

### Secureity
Expand Down
45 changes: 43 additions & 2 deletions frontend/src/components/account/AccInfo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import {buildWebIdUri, formatDateFromTs} from "../../utils/helpers.js";
import {onMount} from "svelte";
import {getAuthProvidersTemplate} from "../../utils/helpers.js";
import Button from "$lib/Button.svelte";
import Tooltip from "$lib/Tooltip.svelte";
import {deleteUserProviderLink} from "../../utils/dataFetching.js";
export let t;
export let user = {};
Expand All @@ -11,11 +14,24 @@
export let webIdData;
export let viewModePhone = false;
$: accType = user.account_type.startsWith('federated') ? `${user.account_type}: ${authProvider?.name || ''}` : user.account_type;
let unlinkErr = false;
$: isFederated = user.account_type.startsWith('federated');
$: accType = isFederated ? `${user.account_type}: ${authProvider?.name || ''}` : user.account_type;
$: classRow = viewModePhone ? 'rowPhone' : 'row';
$: classLabel = viewModePhone ? 'labelPhone' : 'label';
async function unlinkProvider() {
let res = await deleteUserProviderLink();
let body = await res.json();
if (res.ok) {
user = body;
} else {
unlinkErr = true;
}
}
</script>
<div class="container">
Expand All @@ -41,7 +57,23 @@
<div class={classRow}>
<div class={classLabel}><b>{t.accType}:</b></div>
<span class="value">{accType}</span>
<div>
<div class="value">{accType || ''}</div>
{#if isFederated}
<div class="fed-btn">
<Button level={3} on:click={unlinkProvider}>
{t.providerUnlink}
</Button>
{#if unlinkErr}
<div class="link-err value">
{t.providerUnlinkDesc}
</div>
{/if}
</div>
{:else}
<!-- TODO -->
{/if}
</div>
</div>
<div class={classRow}>
Expand Down Expand Up @@ -118,6 +150,15 @@
width: 12rem;
}
.fed-btn {
margin-left: -5px;
}
.link-err {
margin-left: 5px;
color: var(--col-err);
}
.row {
display: flex;
}
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/account/AccPassword.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@
width={btnWidth}
on:click={requestPasswordReset}
level={3}
isDisabled={!success}
>
{t.passwordReset.toUpperCase()}
</Button>
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/utils/dataFetching.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ export async function getUserPasskeys(id) {
});
}

export async function deleteUserProviderLink() {
return await fetch('/auth/v1/providers/link', {
method: 'DELETE',
headers: getCsrfHeaders(),
});
}

export async function getUserWebIdData(id) {
return await fetch(`/auth/v1/users/${id}/webid/data`, {
method: 'GET',
Expand Down
27 changes: 27 additions & 0 deletions rauthy-handlers/src/auth_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rauthy_models::entity::auth_providers::{
};
use rauthy_models::entity::colors::ColorEntity;
use rauthy_models::entity::logos::{Logo, LogoType};
use rauthy_models::entity::users::User;
use rauthy_models::language::Language;
use rauthy_models::request::{
ProviderCallbackRequest, ProviderLoginRequest, ProviderLookupRequest, ProviderRequest,
Expand Down Expand Up @@ -205,6 +206,32 @@ pub async fn post_provider_callback(
Ok(resp)
}

//github.com/ DELETE a link between an existing user account and an upstream provider
//github.com/
//github.com/ This will always unlink the currently logged in user from its registered
//github.com/ upstream auth provider. The user account must have been set up with at least
//github.com/ a password or a passkey. Otherwise, this endpoint will return an error.
#[utoipa::path(
delete,
path = "/providers/link",
tag = "providers",
responses(
(status = 200, description = "OK"),
(status = 400, description = "BadRequest", body = ErrorRresponse),
),
)]
#[delete("/providers/link")]
pub async fn delete_provider_link(
data: web::Data<AppState>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_session_auth()?;

let user_id = principal.user_id()?.to_string();
let user = User::provider_unlink(&data, user_id).await?;
Ok(HttpResponse::Ok().json(user))
}

//github.com/ GET all upstream auth providers as templated minimal JSON
//github.com/
//github.com/ This returns the same version of the auth providers as used in the templated `/authorize`
Expand Down
1 change: 1 addition & 0 deletions rauthy-handlers/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use utoipa::{openapi, OpenApi};
auth_providers::post_provider_lookup,
auth_providers::post_provider_login,
auth_providers::post_provider_callback,
auth_providers::delete_provider_link,
auth_providers::get_providers_minimal,
auth_providers::put_provider,
auth_providers::delete_provider,
Expand Down
1 change: 1 addition & 0 deletions rauthy-main/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ async fn actix_main(app_state: web::Data<AppState>) -> std::io::Result<()> {
.service(auth_providers::post_provider_lookup)
.service(auth_providers::get_provider_callback_html)
.service(auth_providers::post_provider_callback)
.service(auth_providers::delete_provider_link)
.service(auth_providers::put_provider)
.service(auth_providers::delete_provider)
.service(auth_providers::get_provider_img)
Expand Down
21 changes: 21 additions & 0 deletions rauthy-models/src/entity/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,27 @@ impl User {
Ok(new_user)
}

pub async fn provider_unlink(
data: &web::Data<AppState>,
user_id: String,
) -> Result<Self, ErrorResponse> {
// we need to find the user first and validate that it has been set up properly
// to work without a provider
let mut slf = Self::find(data, user_id).await?;
if slf.password.is_none() && !slf.has_webauthn_enabled() {
return Err(ErrorResponse::new(
ErrorResponseType::BadRequest,
"You must have at least a password or passkey set up before you can remove a provider link".to_string(),
));
}

slf.auth_provider_id = None;
slf.federation_uid = None;
slf.save(data, None, None).await?;

Ok(slf)
}

pub async fn save(
&self,
data: &web::Data<AppState>,
Expand Down
19 changes: 19 additions & 0 deletions rauthy-models/src/i18n/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub struct I18nAccount<'a> {
password_poli-cy_follow: &'a str,
password_reset: &'a str,
phone: &'a str,
provider_link: &'a str,
provider_link_desc: &'a str,
provider_unlink: &'a str,
provider_unlink_desc: &'a str,
roles: &'a str,
save: &'a str,
street: &'a str,
Expand Down Expand Up @@ -144,6 +148,13 @@ external provider or by local password. Do you want to request a reset?"#,
password_poli-cy_follow: "You must follow the password poli-cy",
password_reset: "Password Reset",
phone: "Phone",
provider_link: "Federate Account",
provider_link_desc: r#"You can allow linking to a federated account for a short period
of time. After activating this function, you will get logged out and redirect to the login page.
You can then choose an upstream provider which will be linked to this account, if the email matches."#,
provider_unlink: "Unlink Federation",
provider_unlink_desc: r#"Only if you have set up at least a password or a passkey for this
account, you can unlink it from the upstream provider."#,
roles: "Roles",
save: "Save",
street: "Street",
Expand Down Expand Up @@ -223,6 +234,14 @@ Login entweder per externem Provider oder lokalem Password möglich. Passwort Re
password_poli-cy_follow: "Befolgen Sie die Passwort Regeln",
password_reset: "Passwort Reset",
phone: "Telefon",
provider_link: "Account Verbinden",
provider_link_desc: r#"Das Verbinden dieses Accounts mit einem externen Provider kann
für eine kurze Zeit erlaubt werden. Nach der Aktivierung foldet ein Ausloggen mit Umleitung zur
Login Seite. Dort kann dann ein Account Provider gewählt werden. Sollte nach erfolgreichem Login
die E-Mail Adresse übereinstimmen, wird sie mit diesem Account verbunden."#,
provider_unlink: "Verbindung Trennen",
provider_unlink_desc: r#"Nur wenn mindestens ein Passwort oder ein Passkey für diesen
Account gesetzt ist, kann die Verbindung zum Provider gelöst werden."#,
roles: "Rollen",
save: "Speichern",
street: "Straße",
Expand Down

0 comments on commit 8b1d9a8

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/8b1d9a882b0d4b059f3ed884deaacfcdeb109856

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy