mirror of
https://tangled.org/tranquil.farm/tranquil-pds
synced 2026-02-08 21:30:08 +00:00
fix "localhost client" support and use in frontend when in dev mode
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
const OAUTH_STATE_KEY = 'tranquil_pds_oauth_state'
|
||||
const OAUTH_VERIFIER_KEY = 'tranquil_pds_oauth_verifier'
|
||||
const SCOPES = [
|
||||
'atproto',
|
||||
'repo:*?action=create',
|
||||
'repo:*?action=update',
|
||||
'repo:*?action=delete',
|
||||
'blob:*/*',
|
||||
].join(' ')
|
||||
const CLIENT_ID = !(import.meta.env.DEV)
|
||||
? `${window.location.origin}/oauth/client-metadata.json`
|
||||
: `http://localhost/oauth/client-metadata.json?scope=${SCOPES}`
|
||||
const REDIRECT_URI = `${window.location.origin}/`
|
||||
|
||||
interface OAuthState {
|
||||
state: string
|
||||
@@ -65,23 +76,14 @@ export async function startOAuthLogin(): Promise<void> {
|
||||
|
||||
saveOAuthState({ state, codeVerifier })
|
||||
|
||||
const clientId = `${window.location.origin}/oauth/client-metadata.json`
|
||||
const redirectUri = `${window.location.origin}/`
|
||||
|
||||
const parResponse = await fetch('/oauth/par', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
client_id: clientId,
|
||||
redirect_uri: redirectUri,
|
||||
client_id: CLIENT_ID,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
response_type: 'code',
|
||||
scope: [
|
||||
'atproto',
|
||||
'repo:*?action=create',
|
||||
'repo:*?action=update',
|
||||
'repo:*?action=delete',
|
||||
'blob:*/*',
|
||||
].join(' '),
|
||||
scope: SCOPES,
|
||||
state: state,
|
||||
code_challenge: codeChallenge,
|
||||
code_challenge_method: 'S256',
|
||||
@@ -96,7 +98,7 @@ export async function startOAuthLogin(): Promise<void> {
|
||||
const { request_uri } = await parResponse.json()
|
||||
|
||||
const authorizeUrl = new URL('/oauth/authorize', window.location.origin)
|
||||
authorizeUrl.searchParams.set('client_id', clientId)
|
||||
authorizeUrl.searchParams.set('client_id', CLIENT_ID)
|
||||
authorizeUrl.searchParams.set('request_uri', request_uri)
|
||||
|
||||
window.location.href = authorizeUrl.toString()
|
||||
@@ -122,17 +124,14 @@ export async function handleOAuthCallback(code: string, state: string): Promise<
|
||||
throw new Error('OAuth state mismatch. Please try logging in again.')
|
||||
}
|
||||
|
||||
const clientId = `${window.location.origin}/oauth/client-metadata.json`
|
||||
const redirectUri = `${window.location.origin}/`
|
||||
|
||||
const tokenResponse = await fetch('/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: clientId,
|
||||
client_id: CLIENT_ID,
|
||||
code: code,
|
||||
redirect_uri: redirectUri,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
code_verifier: savedState.codeVerifier,
|
||||
}),
|
||||
})
|
||||
@@ -148,14 +147,12 @@ export async function handleOAuthCallback(code: string, state: string): Promise<
|
||||
}
|
||||
|
||||
export async function refreshOAuthToken(refreshToken: string): Promise<OAuthTokens> {
|
||||
const clientId = `${window.location.origin}/oauth/client-metadata.json`
|
||||
|
||||
const tokenResponse = await fetch('/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: clientId,
|
||||
client_id: CLIENT_ID,
|
||||
refresh_token: refreshToken,
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -89,8 +89,9 @@ impl ClientMetadataCache {
|
||||
fn is_loopback_client(client_id: &str) -> bool {
|
||||
if let Ok(url) = reqwest::Url::parse(client_id) {
|
||||
url.scheme() == "http"
|
||||
&& matches!(url.host_str(), Some("localhost") | Some("127.0.0.1"))
|
||||
&& url.query().is_some()
|
||||
&& url.host_str() == Some("localhost")
|
||||
&& url.port().is_none()
|
||||
&& url.path().is_empty()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -98,35 +99,43 @@ impl ClientMetadataCache {
|
||||
|
||||
fn build_loopback_metadata(client_id: &str) -> Result<ClientMetadata, OAuthError> {
|
||||
let url = reqwest::Url::parse(client_id)
|
||||
.map_err(|_| OAuthError::InvalidClient("Invalid loopback client_id URL".to_string()))?;
|
||||
let mut redirect_uris = Vec::new();
|
||||
.map_err(|_| OAuthError::InvalidClient("Invalid loopback client_id URL".into()))?;
|
||||
let mut redirect_uris = Vec::<String>::new();
|
||||
let mut scope: Option<String> = None;
|
||||
for (key, value) in url.query_pairs() {
|
||||
if key == "redirect_uri" {
|
||||
redirect_uris.push(value.to_string());
|
||||
break;
|
||||
}
|
||||
if key == "scope" {
|
||||
scope = Some(value.into());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if redirect_uris.is_empty() {
|
||||
redirect_uris.push("http://127.0.0.1/callback".to_string());
|
||||
redirect_uris.push("http://localhost/callback".to_string());
|
||||
redirect_uris.push("http://127.0.0.1/".into());
|
||||
redirect_uris.push("http://[::1]/".into());
|
||||
}
|
||||
if scope.is_none() {
|
||||
scope = Some("atproto".into());
|
||||
}
|
||||
let scope = Some("atproto transition:generic transition:chat.bsky".to_string());
|
||||
Ok(ClientMetadata {
|
||||
client_id: client_id.to_string(),
|
||||
client_name: Some("Loopback Client".to_string()),
|
||||
client_id: client_id.into(),
|
||||
client_name: Some("Loopback Client".into()),
|
||||
client_uri: None,
|
||||
logo_uri: None,
|
||||
redirect_uris,
|
||||
grant_types: vec![
|
||||
"authorization_code".to_string(),
|
||||
"refresh_token".to_string(),
|
||||
"authorization_code".into(),
|
||||
"refresh_token".into(),
|
||||
],
|
||||
response_types: vec!["code".to_string()],
|
||||
response_types: vec!["code".into()],
|
||||
scope,
|
||||
token_endpoint_auth_method: Some("none".to_string()),
|
||||
token_endpoint_auth_method: Some("none".into()),
|
||||
dpop_bound_access_tokens: Some(false),
|
||||
jwks: None,
|
||||
jwks_uri: None,
|
||||
application_type: Some("native".to_string()),
|
||||
application_type: Some("native".into()),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user