Single sign-on is the only way in when it is configured
The sign-in page shows only the identity provider; password sign-in and new local accounts are refused. Invites go through the identity provider. Server 0.1.2, chart 0.1.3.
This commit is contained in:
1 parent
6114a994db
commit
7c86198002
5 files changed
+34
-25
No files matched your search
Generated
+3
-3
@@ -43,7 +43,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archify-sync-protocol"
|
name = "archify-sync-protocol"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -53,7 +53,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archify-sync-server"
|
name = "archify-sync-server"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archify-sync-protocol",
|
"archify-sync-protocol",
|
||||||
@@ -83,7 +83,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archify-sync-store"
|
name = "archify-sync-store"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ resolver = "3"
|
|||||||
members = ["crates/protocol", "crates/store", "crates/server"]
|
members = ["crates/protocol", "crates/store", "crates/server"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync"
|
repository = "https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync"
|
||||||
@@ -16,7 +16,7 @@ One Rust process and PostgreSQL. The design, with its decisions, is the Archify
|
|||||||
- **Update log:** taking a version compacts it.
|
- **Update log:** taking a version compacts it.
|
||||||
- **Sign-in.** The editor opens `/authorize` in the browser and gets a one-time code back through its URI handler. It exchanges the code with its PKCE verifier for an access token (JWT, 15 minutes) and a refresh token. The refresh token is single use: reusing one signs out the whole session.
|
- **Sign-in.** The editor opens `/authorize` in the browser and gets a one-time code back through its URI handler. It exchanges the code with its PKCE verifier for an access token (JWT, 15 minutes) and a refresh token. The refresh token is single use: reusing one signs out the whole session.
|
||||||
- **First start.** With single sign-on there is no setup step: the identity provider says who may sign in and who is admin, and the first sign-in makes the organisation (named after `ARCHIFY_SYNC_NAME`). Without single sign-on, a server without accounts prints a first-start code in its log; the first person to use it at `/setup` becomes the admin.
|
- **First start.** With single sign-on there is no setup step: the identity provider says who may sign in and who is admin, and the first sign-in makes the organisation (named after `ARCHIFY_SYNC_NAME`). Without single sign-on, a server without accounts prints a first-start code in its log; the first person to use it at `/setup` becomes the admin.
|
||||||
- **Invites.** An invite link (`/join/<token>`) opens the extension. Someone new makes an account on the sign-in page, so no mail server is needed.
|
- **Invites.** An invite link (`/join/<token>`) opens the extension. Someone new makes an account on the sign-in page, so no mail server is needed. With single sign-on, the identity provider is the only way in: the sign-in page has no password form, and an invited person signs in there.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ apiVersion: v2
|
|||||||
name: archify-sync
|
name: archify-sync
|
||||||
description: Archify Sync, live and shared Archify models for VS Code
|
description: Archify Sync, live and shared Archify models for VS Code
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.2
|
version: 0.1.3
|
||||||
appVersion: "0.1.1"
|
appVersion: "0.1.2"
|
||||||
annotations:
|
annotations:
|
||||||
artifacthub.io/license: MIT
|
artifacthub.io/license: MIT
|
||||||
sources:
|
sources:
|
||||||
|
|||||||
+27
-18
@@ -215,24 +215,29 @@ async fn authorize_form(state: &AppState, q: &AuthorizeQuery, error: Option<&str
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
// Single sign-on first when the server has it; the password form stays for local accounts.
|
// With single sign-on the identity provider is the only way in: no
|
||||||
let mut body = state
|
// password form, no new local accounts. An invite goes through it too.
|
||||||
.oidc
|
if let Some(o) = &state.oidc {
|
||||||
.as_ref()
|
let invited = match &q.invite {
|
||||||
.map(|o| {
|
Some(invite) => match state.store.invite_organisation(&auth::sha256(invite)).await {
|
||||||
format!(
|
Ok(Some((_, space_name))) => format!(
|
||||||
r#"<div class="card"><h2>Sign in for VS Code</h2>{}<a class="button" href="/oidc/start?{}">Sign in with {}</a></div>"#,
|
r#"<p class="muted">You were invited to <b>{}</b>.</p>"#,
|
||||||
error_line(error),
|
escape(&space_name)
|
||||||
escape(&q.to_query_string()),
|
),
|
||||||
escape(&o.config.label),
|
_ => String::new(),
|
||||||
)
|
},
|
||||||
})
|
None => String::new(),
|
||||||
.unwrap_or_default();
|
};
|
||||||
let (title, error) = if body.is_empty() {
|
let body = format!(
|
||||||
("Sign in for VS Code", error)
|
r#"<div class="card"><h2>Sign in for VS Code</h2>{}{invited}<a class="button" href="/oidc/start?{}">Sign in with {}</a></div>"#,
|
||||||
} else {
|
error_line(error),
|
||||||
("Or with a password", None)
|
escape(&q.to_query_string()),
|
||||||
};
|
escape(&o.config.label),
|
||||||
|
);
|
||||||
|
return page(state, "Sign in", &body);
|
||||||
|
}
|
||||||
|
let mut body = String::new();
|
||||||
|
let title = "Sign in for VS Code";
|
||||||
body.push_str(&format!(
|
body.push_str(&format!(
|
||||||
r#"<div class="card"><h2>{title}</h2>{}
|
r#"<div class="card"><h2>{title}</h2>{}
|
||||||
<form method="post" action="/authorize">{fields}{}
|
<form method="post" action="/authorize">{fields}{}
|
||||||
@@ -269,6 +274,10 @@ pub async fn authorize_submit(
|
|||||||
if check_authorize(&state, &q).is_err() {
|
if check_authorize(&state, &q).is_err() {
|
||||||
return authorize_form(&state, &q, None).await;
|
return authorize_form(&state, &q, None).await;
|
||||||
}
|
}
|
||||||
|
if let Some(o) = &state.oidc {
|
||||||
|
let message = format!("This server signs in with {} only.", o.config.label);
|
||||||
|
return authorize_form(&state, &q, Some(&message)).await;
|
||||||
|
}
|
||||||
let account = match form.action.as_str() {
|
let account = match form.action.as_str() {
|
||||||
"signup" => sign_up(&state, &form).await,
|
"signup" => sign_up(&state, &form).await,
|
||||||
_ => sign_in(&state, &form).await,
|
_ => sign_in(&state, &form).await,
|
||||||
|
|||||||
Reference in new issue
Block a user