123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- use crate::schema;
- use serde::{Deserialize, Serialize};
- use microrm::prelude::*;
- #[derive(Clone)]
- pub struct ServerState {
- core: &'static super::ServerCoreState,
- }
- type Request = tide::Request<ServerState>;
- #[derive(serde::Serialize)]
- pub enum OIDCErrorType {
- InvalidRequest,
- UnauthorizedClient,
- AccessDenied,
- UnsupportedResponseType,
- InvalidScope,
- ServerError,
- TemporarilyUnavailable,
- }
- pub struct OIDCError<'a>(OIDCErrorType, String, Option<&'a str>);
- impl<'a> OIDCError<'a> {
- fn to_response(self) -> tide::Response {
- #[derive(Serialize)]
- struct ErrorOut<'a> {
- error: OIDCErrorType,
- error_description: String,
- state: Option<&'a str>,
- }
- let eo = ErrorOut {
- error: self.0,
- error_description: self.1,
- state: self.2,
- };
- tide::Response::builder(400)
- .body(serde_json::to_vec(&eo).unwrap())
- .build()
- }
- }
- #[derive(Deserialize)]
- struct AuthorizeQueryParams {
- response_type: String,
- client_id: String,
- redirect_uri: String,
- scope: Option<String>,
- }
- fn do_code_authorize(
- request: Request,
- qp: AuthorizeQueryParams,
- state: Option<&str>,
- client: microrm::WithID<schema::Client>,
- ) -> Result<tide::Response, OIDCError> {
- todo!()
- }
- fn do_token_authorize(
- request: Request,
- qp: AuthorizeQueryParams,
- state: Option<&str>,
- client: microrm::WithID<schema::Client>,
- ) -> Result<tide::Response, OIDCError> {
- todo!()
- }
- fn do_authorize(request: Request, state: Option<&str>) -> Result<tide::Response, OIDCError> {
- let qp: AuthorizeQueryParams = request
- .query()
- .map_err(|x| OIDCError(OIDCErrorType::InvalidRequest, x.to_string(), state))?;
- // verify the realm and client_id and redirect_uri
- let qi = request.state().core.pool.query_interface();
- let realm = qi.get().by(
- schema::Realm::Shortname,
- &request.param("realm").unwrap(),
- ).one().expect("couldn't query db");
- if realm.is_none() {
- return Err(OIDCError(
- OIDCErrorType::InvalidRequest,
- "No such realm!".to_string(),
- state,
- ));
- }
- let realm = realm.unwrap();
- let client = qi.get().by(schema::Client::Realm, &realm.id()).by(schema::Client::Shortname, &qp.client_id).one().expect("couldn't query db");
- if client.is_none() {
- return Err(OIDCError(
- OIDCErrorType::UnauthorizedClient,
- "Client does not exist".to_string(),
- state,
- ));
- }
- if qp.response_type == "code" {
- do_code_authorize(request, qp, state, client.unwrap())
- } else if qp.response_type == "token" {
- do_token_authorize(request, qp, state, client.unwrap())
- } else {
- return Err(OIDCError(
- OIDCErrorType::UnsupportedResponseType,
- "Only code and token are understood.".to_string(),
- state,
- ));
- }
- }
- async fn authorize(request: Request) -> tide::Result<tide::Response> {
- #[derive(Deserialize)]
- struct State {
- state: Option<String>,
- }
- let state: Option<String> = request.query::<State>().ok().map(|x| x.state).flatten();
- let result = do_authorize(request, state.as_ref().map(|x| x.as_str()));
- if let Err(e) = result {
- todo!()
- }
- todo!()
- }
- #[derive(Deserialize)]
- struct TokenRequestBody {
- grant_type: String,
- refresh_token: Option<String>,
- scope: Option<String>,
- redirect_uri: Option<String>,
- code: Option<String>,
- client_id: Option<String>,
- // direct grant
- username: Option<String>,
- password: Option<String>,
- }
- async fn token(mut request: Request) -> tide::Result<tide::Response> {
- let body: Result<TokenRequestBody, _> = request.body_form().await;
- // let body : TokenRequestBody = request.body_form();
- todo!()
- }
- pub fn oidc_v1_server(core: &'static super::ServerCoreState) -> tide::Server<ServerState> {
- let mut srv = tide::with_state(ServerState { core });
- srv.at("authorize").get(authorize).post(authorize);
- srv.at("token").post(token);
- srv
- }
|