Forráskód Böngészése

Update token code to return a Result instead of an Option.

Kestrel 1 éve
szülő
commit
52f2faf741
5 módosított fájl, 60 hozzáadás és 33 törlés
  1. 15 0
      simple-setup.sh
  2. 7 4
      src/cli.rs
  3. 1 0
      src/schema.rs
  4. 7 15
      src/server/oidc.rs
  5. 30 14
      src/token.rs

+ 15 - 0
simple-setup.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+cargo build
+UAUTH=./target/debug/uauth2
+
+$UAUTH init
+$UAUTH cert generate
+$UAUTH client create testclient
+$UAUTH user create kestrel
+echo "please enter password for user 'kestrel'"
+$UAUTH user auth -p kestrel
+
+$UAUTH config load /dev/stdin <<EOF
+base_url = "http://localhost:2114/"
+EOF

+ 7 - 4
src/cli.rs

@@ -277,10 +277,13 @@ impl TokenArgs {
                         .id(),
                     scopes.split_whitespace(),
                 );
-                if let Some(t) = token {
-                    println!("token: {t}");
-                } else {
-                    println!("Could not generate token");
+                match token {
+                    Ok(t) => {
+                        println!("token: {t}");
+                    }
+                    Err(e) => {
+                        println!("could not generate token: {:?}", e);
+                    }
                 }
             }
             TokenCommand::GenerateRefresh {

+ 1 - 0
src/schema.rs

@@ -160,6 +160,7 @@ pub fn schema() -> Schema {
         .entity::<User>()
         .entity::<AuthChallenge>()
         .entity::<Group>()
+        .entity::<GroupMembership>()
         .entity::<Client>()
         .index::<ClientNameIndex>()
         .entity::<ClientRedirect>()

+ 7 - 15
src/server/oidc.rs

@@ -98,21 +98,13 @@ fn do_token_authorize(
         scopes,
     );
 
-    if let Some(token) = token {
-        let response_body = serde_json::json!({
-            "token": token,
-        });
-        Ok(tide::Response::builder(200)
-            .content_type(tide::http::mime::JSON)
-            .body(response_body)
-            .build())
-    } else {
-        Err(OIDCError(
-            OIDCErrorType::ServerError,
-            "internal error while generating token".to_string(),
-            state,
-        ))
-    }
+    let response_body = serde_json::json!({
+        "token": token.map_err(|e| OIDCError(OIDCErrorType::ServerError, format!("error while generating token: {:?}", e), state))?,
+    });
+    Ok(tide::Response::builder(200)
+        .content_type(tide::http::mime::JSON)
+        .body(response_body)
+        .build())
 }
 
 fn do_authorize(request: Request, state: Option<&str>) -> Result<tide::Response, OIDCError> {

+ 30 - 14
src/token.rs

@@ -1,6 +1,25 @@
 use crate::{config, jwt, schema};
 use microrm::{entity::EntityID, prelude::*};
 
+#[derive(Debug)]
+pub enum TokenError {
+    DBError(microrm::Error),
+    InternalError(&'static str),
+    RequestError(&'static str),
+}
+
+impl From<microrm::Error> for TokenError {
+    fn from(value: microrm::Error) -> Self {
+        Self::DBError(value)
+    }
+}
+
+impl From<ring::error::KeyRejected> for TokenError {
+    fn from(value: ring::error::KeyRejected) -> Self {
+        Self::InternalError("could not load realm key")
+    }
+}
+
 pub fn generate_auth_token<'a>(
     config: &config::Config,
     qi: &microrm::QueryInterface,
@@ -8,10 +27,10 @@ pub fn generate_auth_token<'a>(
     client: schema::ClientID,
     user: schema::UserID,
     scopes: impl Iterator<Item = &'a str>,
-) -> Option<String> {
-    let realm = qi.get().by_id(&realm).one().ok()??;
-    let client = qi.get().by_id(&client).one().ok()??;
-    let user = qi.get().by_id(&user).one().ok()??;
+) -> Result<String, TokenError> {
+    let realm = qi.get().by_id(&realm).one()?.ok_or(TokenError::RequestError("no such realm"))?;
+    let client = qi.get().by_id(&client).one()?.ok_or(TokenError::RequestError("no such client"))?;
+    let user = qi.get().by_id(&user).one()?.ok_or(TokenError::RequestError("no such user"))?;
 
     let issuer = format!("{}/{}", config.base_url, realm.shortname,);
 
@@ -23,14 +42,12 @@ pub fn generate_auth_token<'a>(
     for group in qi
         .get()
         .by(schema::GroupMembership::User, &user.id())
-        .all()
-        .ok()?
+        .all()?
     {
         for group_role in qi
             .get()
             .by(schema::GroupRole::Group, &group.id())
-            .all()
-            .ok()?
+            .all()?
         {
             user_roles.push(group_role.role);
         }
@@ -39,12 +56,11 @@ pub fn generate_auth_token<'a>(
     // find all roles requested by the scopes
     let mut requested_roles = vec![];
     for scope in scopes {
-        if let Some(scope) = qi.get().by(schema::Scope::Shortname, scope).one().ok()? {
+        if let Some(scope) = qi.get().by(schema::Scope::Shortname, scope).one()? {
             for scope_role in qi
                 .get()
                 .by(schema::ScopeRole::Scope, &scope.id())
-                .all()
-                .ok()?
+                .all()?
             {
                 requested_roles.push(scope_role.role);
             }
@@ -85,8 +101,8 @@ pub fn generate_auth_token<'a>(
         .into(),
     };
 
-    let key = qi.get().by(schema::Key::Realm, &realm.id()).one().ok()??;
-    let kpair = ring::signature::Ed25519KeyPair::from_pkcs8(key.keydata.as_slice()).ok()?;
+    let key = qi.get().by(schema::Key::Realm, &realm.id()).one()?.ok_or(TokenError::InternalError("no signing key for realm"))?;
+    let kpair = ring::signature::Ed25519KeyPair::from_pkcs8(key.keydata.as_slice())?;
 
-    Some(jwt::JWT::sign(&kpair, token).into_string())
+    Ok(jwt::JWT::sign(&kpair, token).into_string())
 }