yinho999 / loco-oauth2

9 stars 6 forks source link

Example of how to call `google_callback_jwt` outside of `get` function. #7

Closed BWStearns closed 4 months ago

BWStearns commented 4 months ago

For my user's login flow I'm trying to get the jwt from google_callback_jwt and attach it as a query param for a redirect to our login success page. I'm having issues figuring out what the actual call should look like (since the get function is handling it with some indirection I don't full understand yet). I want to do something like the following where I ultimately call redirect(&format!("/login?token={}", token)) with the JWT that google_callback_jwt gives back. Is there an example I could follow for this pattern or do I need to write a different implementation of google_callback_jwt that only returns the token and not an IntoResponse?

// Call google_callback_jwt and redirect to login
async fn get_google_jwt_and_route_to_login(
    ctx: State<AppContext>,
    user: OAuth2CookieUser<OAuth2UserProfile, users::Model, o_auth2_sessions::Model>,
    state: State<AppContext>,

) -> Result<Response> {
    let store = ctx.get::<OAuth2ClientStore>()?;
    let token = google_callback_jwt(
        ctx, 
        user,
        state,
        store,
    ).await.unwrap();
    // redirect to login with jwt token in the query string
    redirect(&format!("/login?token={}", token))
}
yinho999 commented 4 months ago

@BWStearns In your case, you can modify the default google_callback_jwt function

pub async fn google_callback_jwt(
    State(ctx): State<AppContext>,
    session: Session<SessionNullPool>,
    Query(params): Query<AuthParams>,
    Extension(oauth2_store): Extension<OAuth2ClientStore>,
) -> Result<impl IntoResponse> {
    let mut client = oauth2_store
        .get_authorization_code_client("google")
        .await
        .map_err(|e| {
            tracing::error!("Error getting client: {:?}", e);
            Error::InternalServerError
        })?;
    // Get JWT secret from the config
    let jwt_secret = ctx.config.get_jwt_config()?;
    let user = callback_jwt::<OAuth2UserProfile, users::Model, o_auth2_sessions::Model, SessionNullPool>(&ctx, session, params, &mut client).await?;
    drop(client);
    let token = user
        .generate_jwt(&jwt_secret.secret, &jwt_secret.expiration)
        .or_else(|_| unauthorized("unauthorized!"))?;
    // Redirect
    redirect(&format!("/login?token={}", token))
}
BWStearns commented 4 months ago

Thanks a ton. That worked!