-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2c2ce07
commit ba965e4
Showing
8 changed files
with
124 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,51 @@ | ||
use axum::Extension; | ||
use crate::models::app::AppState; | ||
use crate::models::auth::{AuthRequest, UserProfile}; | ||
use crate::service::auth::create_or_get_user_id; | ||
use axum::extract::{Query, State}; | ||
use axum::http::StatusCode; | ||
use axum::response::IntoResponse; | ||
use axum::Extension; | ||
use log::error; | ||
use oauth2::{AuthorizationCode, TokenResponse}; | ||
use oauth2::basic::BasicClient; | ||
use oauth2::reqwest::async_http_client; | ||
use crate::models::app::AppState; | ||
use crate::models::auth::{AuthRequest, UserProfile}; | ||
use crate::service::auth::create_or_get_user_id; | ||
use oauth2::{AuthorizationCode, TokenResponse}; | ||
|
||
/// This function handles the passing in of the Google OAuth code. After allowing our app the | ||
/// requested permissions, the user is redirected to this url on our server, where we use the | ||
/// code to get the user's email address from Google's OpenID Connect API. | ||
pub async fn google_callback( | ||
State(state): State<AppState>, | ||
Query(query): Query<AuthRequest>, | ||
Extension(oauth_client): Extension<BasicClient> | ||
Extension(oauth_client): Extension<BasicClient>, | ||
) -> Result<impl IntoResponse, impl IntoResponse> { | ||
let token = match oauth_client | ||
.exchange_code(AuthorizationCode::new(query.code)) | ||
.request_async(async_http_client) | ||
.await { | ||
.await | ||
{ | ||
Ok(res) => res, | ||
Err(e) => { | ||
error!("An error occured while exchanging Google OAuth code"); | ||
return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) | ||
return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())); | ||
} | ||
}; | ||
|
||
let profile = match state.ctx.get("https://openidconnect.googleapis.com/v1/userinfo") | ||
let profile = match state | ||
.ctx | ||
.get("https://openidconnect.googleapis.com/v1/userinfo") | ||
.bearer_auth(token.access_token().secret().to_owned()) | ||
.send().await { | ||
.send() | ||
.await | ||
{ | ||
Ok(res) => res, | ||
Err(e) => return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) | ||
Err(e) => return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())), | ||
}; | ||
|
||
let profile = profile.json::<UserProfile>().await.unwrap(); | ||
// let profile = profile.json::<UserProfile>().await?; | ||
|
||
let user_id = create_or_get_user_id(profile.email, state.db).await?; | ||
// let user_id = create_or_get_user_id(profile.email, state.db).await?; | ||
|
||
// TODO: Create a JWT from this user_id and return to the user. | ||
} | ||
Ok("woohoo") | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
use sqlx::{Pool, Postgres}; | ||
use jsonwebtoken::{DecodingKey, EncodingKey}; | ||
use reqwest::Client as ReqwestClient; | ||
use sqlx::{Pool, Postgres}; | ||
|
||
#[derive(Clone)] | ||
pub struct AppState { | ||
pub db: Pool<Postgres>, | ||
pub ctx: ReqwestClient | ||
} | ||
pub ctx: ReqwestClient, | ||
pub decoding_key: DecodingKey, | ||
pub encoding_key: EncodingKey, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,34 @@ | ||
use axum::{ | ||
async_trait, | ||
extract::FromRequest, | ||
http::{self, Request}, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Deserialize, Serialize)] | ||
pub struct AuthRequest { | ||
pub code: String | ||
pub code: String, | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
pub struct UserProfile { | ||
pub email: String | ||
} | ||
pub email: String, | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
pub struct AuthUser { | ||
pub user_id: i64, | ||
} | ||
|
||
#[async_trait] | ||
impl<S, B> FromRequest<S, B> for AuthUser | ||
where | ||
B: Send + 'static, | ||
S: Send + Sync, | ||
{ | ||
type Rejection = http::StatusCode; | ||
|
||
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { | ||
Ok(AuthUser { user_id: 1 }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use axum::extract::State; | ||
use jsonwebtoken::Algorithm; | ||
use jsonwebtoken::{decode, Validation}; | ||
use serde::{Deserialize, Serialize}; | ||
use uuid::Uuid; | ||
|
||
use crate::AppState; | ||
|
||
#[derive(Debug, Deserialize, Serialize)] | ||
pub struct AuthorizationJwtPayload { | ||
pub iss: String, // issuer | ||
pub sub: String, // subject (user's id) | ||
pub jti: Uuid, // id | ||
pub aud: Vec<String>, // audience (uri the JWT is meant for) | ||
|
||
// Time-based validity | ||
pub exp: i64, // expiry (UNIX timestamp) | ||
pub nbf: i64, // not-valid-before (UNIX timestamp) | ||
pub iat: i64, // issued-at (UNIX timestamp) | ||
|
||
pub username: String, // username | ||
} | ||
|
||
pub fn decode_auth_token( | ||
token: String, | ||
State(state): State<AppState>, | ||
) -> Option<AuthorizationJwtPayload> { | ||
let decode_token = decode::<AuthorizationJwtPayload>( | ||
token.as_str(), | ||
&state.decoding_key, | ||
&Validation::new(Algorithm::HS256), | ||
); | ||
|
||
return match decode_token { | ||
Ok(token) => Option::from(token.claims), | ||
Err(_err) => None::<AuthorizationJwtPayload>, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod auth; | ||
pub mod jwt; | ||
pub mod oauth2; |