oidc.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. use crate::schema;
  2. use serde::{Deserialize, Serialize};
  3. use microrm::prelude::*;
  4. #[derive(Clone)]
  5. pub struct ServerState {
  6. core: &'static super::ServerCoreState,
  7. }
  8. type Request = tide::Request<ServerState>;
  9. #[derive(serde::Serialize)]
  10. pub enum OIDCErrorType {
  11. InvalidRequest,
  12. UnauthorizedClient,
  13. AccessDenied,
  14. UnsupportedResponseType,
  15. InvalidScope,
  16. ServerError,
  17. TemporarilyUnavailable,
  18. }
  19. pub struct OIDCError<'a>(OIDCErrorType, String, Option<&'a str>);
  20. impl<'a> OIDCError<'a> {
  21. fn to_response(self) -> tide::Response {
  22. #[derive(Serialize)]
  23. struct ErrorOut<'a> {
  24. error: OIDCErrorType,
  25. error_description: String,
  26. state: Option<&'a str>,
  27. }
  28. let eo = ErrorOut {
  29. error: self.0,
  30. error_description: self.1,
  31. state: self.2,
  32. };
  33. tide::Response::builder(400)
  34. .body(serde_json::to_vec(&eo).unwrap())
  35. .build()
  36. }
  37. }
  38. #[derive(Deserialize)]
  39. struct AuthorizeQueryParams {
  40. response_type: String,
  41. client_id: String,
  42. redirect_uri: String,
  43. scope: Option<String>,
  44. }
  45. fn do_code_authorize(
  46. request: Request,
  47. qp: AuthorizeQueryParams,
  48. state: Option<&str>,
  49. client: microrm::WithID<schema::Client>,
  50. ) -> Result<tide::Response, OIDCError> {
  51. todo!()
  52. }
  53. fn do_token_authorize(
  54. request: Request,
  55. qp: AuthorizeQueryParams,
  56. state: Option<&str>,
  57. client: microrm::WithID<schema::Client>,
  58. ) -> Result<tide::Response, OIDCError> {
  59. todo!()
  60. }
  61. fn do_authorize(request: Request, state: Option<&str>) -> Result<tide::Response, OIDCError> {
  62. let qp: AuthorizeQueryParams = request
  63. .query()
  64. .map_err(|x| OIDCError(OIDCErrorType::InvalidRequest, x.to_string(), state))?;
  65. // verify the realm and client_id and redirect_uri
  66. let qi = request.state().core.pool.query_interface();
  67. let realm = qi.get().by(
  68. schema::Realm::Shortname,
  69. &request.param("realm").unwrap(),
  70. ).one().expect("couldn't query db");
  71. if realm.is_none() {
  72. return Err(OIDCError(
  73. OIDCErrorType::InvalidRequest,
  74. "No such realm!".to_string(),
  75. state,
  76. ));
  77. }
  78. let realm = realm.unwrap();
  79. let client = qi.get().by(schema::Client::Realm, &realm.id()).by(schema::Client::Shortname, &qp.client_id).one().expect("couldn't query db");
  80. if client.is_none() {
  81. return Err(OIDCError(
  82. OIDCErrorType::UnauthorizedClient,
  83. "Client does not exist".to_string(),
  84. state,
  85. ));
  86. }
  87. if qp.response_type == "code" {
  88. do_code_authorize(request, qp, state, client.unwrap())
  89. } else if qp.response_type == "token" {
  90. do_token_authorize(request, qp, state, client.unwrap())
  91. } else {
  92. return Err(OIDCError(
  93. OIDCErrorType::UnsupportedResponseType,
  94. "Only code and token are understood.".to_string(),
  95. state,
  96. ));
  97. }
  98. }
  99. async fn authorize(request: Request) -> tide::Result<tide::Response> {
  100. #[derive(Deserialize)]
  101. struct State {
  102. state: Option<String>,
  103. }
  104. let state: Option<String> = request.query::<State>().ok().map(|x| x.state).flatten();
  105. let result = do_authorize(request, state.as_ref().map(|x| x.as_str()));
  106. if let Err(e) = result {
  107. todo!()
  108. }
  109. todo!()
  110. }
  111. #[derive(Deserialize)]
  112. struct TokenRequestBody {
  113. grant_type: String,
  114. refresh_token: Option<String>,
  115. scope: Option<String>,
  116. redirect_uri: Option<String>,
  117. code: Option<String>,
  118. client_id: Option<String>,
  119. // direct grant
  120. username: Option<String>,
  121. password: Option<String>,
  122. }
  123. async fn token(mut request: Request) -> tide::Result<tide::Response> {
  124. let body: Result<TokenRequestBody, _> = request.body_form().await;
  125. // let body : TokenRequestBody = request.body_form();
  126. todo!()
  127. }
  128. pub fn oidc_v1_server(core: &'static super::ServerCoreState) -> tide::Server<ServerState> {
  129. let mut srv = tide::with_state(ServerState { core });
  130. srv.at("authorize").get(authorize).post(authorize);
  131. srv.at("token").post(token);
  132. srv
  133. }