feat: support OIDC id_token
- generate JWT id_token in token exchange - store optional nonce in authorization object - switch to RS256 algorithm for JWT signature - add JWKs endpoint to provide OIDC clients with public keys
This commit is contained in:
parent
ca84a0f99f
commit
d982f2af0d
29 changed files with 255 additions and 82 deletions
|
|
@ -7,9 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
use kernel::{
|
||||
models::{authorization::Authorization, config::AppAuthorizeFlow}
|
||||
};
|
||||
use kernel::models::{authorization::Authorization, config::AppAuthorizeFlow};
|
||||
use utils::get_random_alphanumerical;
|
||||
use crate::{
|
||||
renderer::TemplateRenderer, services::oauth2::{parse_scope, verify_redirect_uri}, token_claims::UserTokenClaims, AppState
|
||||
|
|
@ -25,6 +23,7 @@ struct AuthorizationParams {
|
|||
redirect_uri: String,
|
||||
/// An opaque value used by the client to maintain state between the request and callback
|
||||
state: String,
|
||||
nonce: Option<String>
|
||||
}
|
||||
|
||||
fn redirect_to_client(
|
||||
|
|
@ -34,7 +33,7 @@ fn redirect_to_client(
|
|||
let target_url = format!("{}?code={}&state={}",
|
||||
authorization_params.redirect_uri,
|
||||
authorization_code,
|
||||
authorization_params.state,
|
||||
authorization_params.state
|
||||
);
|
||||
debug!("Redirecting to {}", target_url);
|
||||
|
||||
|
|
@ -117,9 +116,10 @@ pub async fn authorize_form(
|
|||
// Create new auth code
|
||||
let authorization_code = get_random_alphanumerical(32);
|
||||
// Update last used timestamp for this authorization
|
||||
let _result = sqlx::query("UPDATE authorizations SET code = $2, last_used_at = $3 WHERE id = $1")
|
||||
let _result = sqlx::query("UPDATE authorizations SET code = $2, nonce = $3, last_used_at = $4 WHERE id = $1")
|
||||
.bind(existing_authorization.id)
|
||||
.bind(authorization_code.clone())
|
||||
.bind(authorization_params.nonce.clone())
|
||||
.bind(Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true))
|
||||
.execute(&app_state.db.0)
|
||||
.await.unwrap();
|
||||
|
|
@ -173,6 +173,7 @@ pub async fn perform_authorize(
|
|||
Extension(token_claims): Extension<UserTokenClaims>,
|
||||
Form(authorize_form): Form<AuthorizationParams>
|
||||
) -> impl IntoResponse {
|
||||
dbg!(&authorize_form);
|
||||
// 1. Get the app details
|
||||
let app = match app_state.config.applications
|
||||
.iter()
|
||||
|
|
@ -204,6 +205,7 @@ pub async fn perform_authorize(
|
|||
client_id: app.client_id.clone(),
|
||||
scopes: sqlx::types::Json(scopes),
|
||||
code: authorization_code.clone(),
|
||||
nonce: authorize_form.nonce.clone(),
|
||||
last_used_at: Some(Utc::now()),
|
||||
created_at: Utc::now(),
|
||||
};
|
||||
|
|
@ -211,14 +213,15 @@ pub async fn perform_authorize(
|
|||
// 3. Save authorization in DB with state
|
||||
let res = sqlx::query("
|
||||
INSERT INTO authorizations
|
||||
(id, user_id, client_id, scopes, code, last_used_at, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
(id, user_id, client_id, scopes, code, nonce, last_used_at, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
")
|
||||
.bind(authorization.id.clone())
|
||||
.bind(authorization.user_id)
|
||||
.bind(authorization.client_id)
|
||||
.bind(authorization.scopes)
|
||||
.bind(authorization.code)
|
||||
.bind(authorization.nonce)
|
||||
.bind(authorization.last_used_at.map(|x| x.to_rfc3339_opts(SecondsFormat::Millis, true)))
|
||||
.bind(authorization.created_at.to_rfc3339_opts(SecondsFormat::Millis, true))
|
||||
.execute(&app_state.db.0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue