~starkingdoms/starkingdoms

ref: 603d2bb46d38fa7d4c46df4cb9aad895916ec011 starkingdoms/api/src/routes/callback.rs -rw-r--r-- 2.3 KiB
603d2bb4 — c0repwn3r work on callback 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::collections::BTreeMap;
use actix_web::{get, HttpResponse};
use actix_web::web::{Data, Query};
use jwt::{PKeyWithDigest, VerifyWithKey};
use log::{debug, error};
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use serde::Deserialize;
use crate::AppState;
use crate::config::CONFIG;
use crate::error::{APIError, APIErrorsResponse};

#[derive(Deserialize)]
pub struct CallbackQueryParams {
    pub token: String,
    pub realm: String
}

#[get("/callback")]
pub async fn callback(query: Query<CallbackQueryParams>, state: Data<AppState>) -> HttpResponse {
    // verify token from auth provider API

    // 1. load the public key
    let realm = match CONFIG.realms.get(&query.realm) {
        Some(r) => r,
        None => {
            error!("realm not found");
            return HttpResponse::Unauthorized().json(APIErrorsResponse {
                errors: vec![
                    APIError {
                        code: "ERR_UNKNOWN_REALM".to_string(),
                        message: "Unknown realm".to_string(),
                        path: None,
                    }
                ],
            })
        }
    };

    let rs256_pub_key = PKeyWithDigest {
        digest: MessageDigest::sha256(),
        key: PKey::public_key_from_pem(realm.public_key.as_bytes()).unwrap()
    };

    let token: BTreeMap<String, String> = match query.token.verify_with_key(&rs256_pub_key) {
        Ok(tkn) => tkn,
        Err(e) => {
            error!("[callback] token verify error: {}", e);
            return generic_unauthorized();
        }
    };

    let realm = match token.get("realm").ok_or(generic_unauthorized()) {
        Ok(r) => r,
        Err(e) => return e
    };
    let realm_local_id = match token.get("realm_native_id").ok_or(generic_unauthorized()) {
        Ok(r) => r,
        Err(e) => return e
    };

    debug!("got authenticated realm native authorization: authenticated as {}:{}", realm, realm_local_id);

    HttpResponse::Ok().finish()
}

fn generic_unauthorized() -> HttpResponse {
    HttpResponse::Unauthorized().json(APIErrorsResponse {
        errors: vec![
            APIError {
                code: "ERR_INVALID_STATE".to_string(),
                message: "Unknown/invalid login state".to_string(),
                path: None,
            }
        ],
    })
}