Commit 1c2e0d81 authored by Szymon Zimnowoda's avatar Szymon Zimnowoda
Browse files

authorization endpoint

parent a93db914
Showing with 143 additions and 28 deletions
+143 -28
-- Oauth2Flow {
-- "accessToken": secret, string,
-- "refreshToken": secret, string,
-- "tokenType": ex. "bearer", string,
-- "redirectUri": ex. example.com/oauth2, string,
-- "service": ex. "gitlab", string,
-- }
-- "accessToken": secret, string,
INSERT INTO items(id, type, dateCreated, dateModified, dateServerModified, deleted) VALUES(
"a39b37f8-8408-4d59-b6aa-24025beaec7e",
"ItemPropertySchema", 0, 0, 0, 0
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "a39b37f8-8408-4d59-b6aa-24025beaec7e"),
"itemType", "Trigger"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "a39b37f8-8408-4d59-b6aa-24025beaec7e"),
"propertyName", "accessToken"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "a39b37f8-8408-4d59-b6aa-24025beaec7e"),
"valueType", "Text"
);
-- "refreshToken": secret, string,
INSERT INTO items(id, type, dateCreated, dateModified, dateServerModified, deleted) VALUES(
"e2b5f1e0-fcff-4fea-8a07-f97c581523cb",
"ItemPropertySchema", 0, 0, 0, 0
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "e2b5f1e0-fcff-4fea-8a07-f97c581523cb"),
"itemType", "Trigger"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "e2b5f1e0-fcff-4fea-8a07-f97c581523cb"),
"propertyName", "refreshToken"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "e2b5f1e0-fcff-4fea-8a07-f97c581523cb"),
"valueType", "Text"
);
-- "tokenType": ex. "bearer", string,
INSERT INTO items(id, type, dateCreated, dateModified, dateServerModified, deleted) VALUES(
"6c7f5ca7-a0d8-404e-ac86-64e59d87802f",
"ItemPropertySchema", 0, 0, 0, 0
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "6c7f5ca7-a0d8-404e-ac86-64e59d87802f"),
"itemType", "Trigger"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "6c7f5ca7-a0d8-404e-ac86-64e59d87802f"),
"propertyName", "tokenType"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "6c7f5ca7-a0d8-404e-ac86-64e59d87802f"),
"valueType", "Text"
);
-- "redirectUri": ex. example.com/oauth2, string,
INSERT INTO items(id, type, dateCreated, dateModified, dateServerModified, deleted) VALUES(
"82c0eeb8-a232-4cb3-abef-8c17c40dbfc1",
"ItemPropertySchema", 0, 0, 0, 0
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "82c0eeb8-a232-4cb3-abef-8c17c40dbfc1"),
"itemType", "Trigger"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "82c0eeb8-a232-4cb3-abef-8c17c40dbfc1"),
"propertyName", "redirectUri"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "82c0eeb8-a232-4cb3-abef-8c17c40dbfc1"),
"valueType", "Text"
);
-- "service": ex. "gitlab", string,
INSERT INTO items(id, type, dateCreated, dateModified, dateServerModified, deleted) VALUES(
"8c96cc39-47af-430c-92cd-f9d43c1da058",
"ItemPropertySchema", 0, 0, 0, 0
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "8c96cc39-47af-430c-92cd-f9d43c1da058"),
"itemType", "Trigger"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "8c96cc39-47af-430c-92cd-f9d43c1da058"),
"propertyName", "service"
);
INSERT INTO strings(item, name, value) VALUES(
(SELECT rowid FROM items WHERE id = "8c96cc39-47af-430c-92cd-f9d43c1da058"),
"valueType", "Text"
);
\ No newline at end of file
......@@ -23,9 +23,9 @@ use oauth2::{
use reqwest::StatusCode;
use rusqlite::Transaction;
use serde::{Deserialize, Serialize};
use serde_json::json;
use serde_json::{json, Value};
use std::{collections::HashMap, env};
use tracing::debug;
use tracing::{debug, trace};
type Oauth2Client<PlatformExtras> = Client<
BasicErrorResponse,
......@@ -49,7 +49,7 @@ impl ExtraTokenFields for GitlabExtras {}
pub async fn auth_url(payload: Oauth2AuthUrlRequest) -> Result<String> {
debug!("Creating auth url for {:?}", payload.platform);
let client = get_client::<EmptyExtraTokenFields>(payload.platform)?
let client = get_client::<EmptyExtraTokenFields>(&payload.platform)?
.set_redirect_uri(RedirectUrl::new(payload.redirect_uri)?);
let (authorize_url, _csrf_state) = client
......@@ -88,26 +88,34 @@ pub async fn authorize<'conn>(
) -> Result<Oauth2AccessTokenResponse> {
debug!("Authorizing token for {:?}", payload.platform);
match payload.platform {
Platforms::Gitlab => {
let platform = payload.platform.clone();
let token = exchange_code::<GitlabExtras>(payload).await?;
let a = json!({
"accessToken": token.access_token().secret(),
}).as_object().unwrap().to_owned();
let token = exchange_code::<GitlabExtras>(&payload).await?;
// TODO: magic string to constants
let item = CreateItem {
_type: "Oauth2Flow".to_string(),
fields: a.into()
,
fields: json!({
"accessToken": token.access_token().secret(),
"refreshToken": token.refresh_token().expect("missing refresh token").secret(),
"tokenType": token.token_type().as_ref().to_string(),
"redirectUri": payload.redirect_uri,
"service": payload.platform,
// TODO: needed at all?
// "expiresIn": token.expires_in().map(|d| d.as_secs()),
// "createdAt": Some(token.extra_fields().created_at),
})
.as_object()
.expect("Invalid json object for oauth2")
.to_owned()
.into_iter()
.collect(),
..Default::default()
};
let a = internal_api::create_item_tx(tx, schema, item, &owner, cli);
// let token = exchange_refresh_token::<GitlabExtras>(payload).await?;
let id = internal_api::create_item_tx(tx, schema, item, &owner, cli)?;
trace!("Access token for {:?}, created {id}", payload.platform);
Ok(Oauth2AccessTokenResponse {
access_token: token.access_token().secret().clone(),
......@@ -149,13 +157,13 @@ lazy_static! {
// }
async fn exchange_code<PlatformExtras: ExtraTokenFields>(
payload: Oauth2AuthorizeTokenRequest,
payload: &Oauth2AuthorizeTokenRequest,
) -> Result<CustomTokenResponse<PlatformExtras>> {
let client =
get_client(payload.platform)?.set_redirect_uri(RedirectUrl::new(payload.redirect_uri)?);
let client = get_client(&payload.platform)?
.set_redirect_uri(RedirectUrl::new(payload.redirect_uri.clone())?);
Ok(client
.exchange_code(AuthorizationCode::new(payload.auth_code))
.exchange_code(AuthorizationCode::new(payload.auth_code.clone()))
.request_async(async_http_client)
.await?)
}
......@@ -164,9 +172,9 @@ async fn exchange_code<PlatformExtras: ExtraTokenFields>(
/// Client defines exact type of token response, it might be different per platform
/// The details are defined by PlatformExtras template parameter
fn get_client<PlatformExtras: ExtraTokenFields>(
platform: Platforms,
platform: &Platforms,
) -> Result<Oauth2Client<PlatformExtras>> {
let config = PLATFORM_CONFIG.get(&platform).ok_or(Error {
let config = PLATFORM_CONFIG.get(platform).ok_or(Error {
code: StatusCode::INTERNAL_SERVER_ERROR,
msg: format!("Missing configuration for {platform:?}"),
})?;
......
......@@ -123,8 +123,9 @@ pub async fn run_server<S: 'static>(cli_options: CliOptions, trace_handle: Handl
.and(warp::path::end())
.and(warp::body::bytes())
.and(with_init_db())
.then(|owner: PodOwner, body: Bytes, init_db: Arc<InitDb>| async move {
warp_endpoints::oauth2_authorize(owner, body, init_db.deref()).await
.and(with_cli())
.then(|owner: PodOwner, body: Bytes, init_db: Arc<InitDb>, cli: Arc<CliOptions>| async move {
warp_endpoints::oauth2_authorize(owner, body, init_db.deref(), cli.deref()).await
})
.boxed();
......
......@@ -169,9 +169,13 @@ async fn _oauth2_access_token(body: Bytes) -> Result<Oauth2AccessTokenResponse>
}
#[instrument(fields(uid=trace_uid(), %owner), skip_all)]
pub async fn oauth2_authorize(owner: PodOwner, body: Bytes, init_db: &InitDb) -> Response {
let result = _oauth2_authorize(&owner, body, init_db).await;
pub async fn oauth2_authorize(
owner: PodOwner,
body: Bytes,
init_db: &InitDb,
cli: &CliOptions,
) -> Response {
let result = _oauth2_authorize(&owner, body, init_db, cli).await;
let result = result.map(|result| warp::reply::json(&result));
respond_with_result(result)
}
......@@ -180,6 +184,7 @@ async fn _oauth2_authorize(
owner: &PodOwner,
body: Bytes,
init_db: &InitDb,
cli: &CliOptions,
) -> Result<Oauth2AccessTokenResponse> {
let body = &mut serde_json::Deserializer::from_slice(body.deref());
let body: PayloadWrapper<Oauth2AuthorizeTokenRequest> = serde_path_to_error::deserialize(body)?;
......@@ -195,10 +200,9 @@ async fn _oauth2_authorize(
in_write_transaction(&mut conn, |tx| {
let mut schema = database_api::get_schema(tx)?;
tokio::runtime::Handle::current().block_on(async {
tokio::runtime::Handle::current().block_on(async {
// do something async
oauth2_api::authorize(tx, &mut schema, &owner, cli, payload).await
})
})
})
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment