Skip to content

Commit

Permalink
feat(session): add create session cookie feature
Browse files Browse the repository at this point in the history
  • Loading branch information
stephane-ein committed Aug 18, 2020
1 parent c0dc41a commit 2996fd0
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ chrono = { version = "0.4", features = ["serde"] }
biscuit = "0.4"
ring = "0.16"
base64 = "0.11"
jsonwebtoken = "7"

[dependencies.rocket]
version = "0.4.2"
Expand Down
87 changes: 87 additions & 0 deletions src/sessions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::slice::Iter;
pub mod user {
use super::*;
use credentials::Credentials;
use std::time::{SystemTime, UNIX_EPOCH};
use jsonwebtoken::{Algorithm, encode, EncodingKey, Header};

#[inline]
fn token_endpoint(v: &str) -> String {
Expand Down Expand Up @@ -138,6 +140,40 @@ pub mod user {
project_id: String,
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
#[allow(non_snake_case)]
struct SessionLogin {
idToken: String,
validDuration: u64,
}

#[derive(Debug, Deserialize)]
struct Oauth2Response {
access_token: String,
expires_in: u64,
token_type: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
scope: String,
aud: String,
exp: u64,
iat: u64,
iss: String,
}

#[derive(Debug, Deserialize)]
#[allow(non_snake_case)]
struct CreateSessionCookieResponseJson {
sessionCookie: String,
}

#[derive(Debug, Deserialize)]
pub struct CreateSessionCookie {
pub session_cookie: String,
}

impl Session {
/// Create an impersonated session
///
Expand Down Expand Up @@ -270,6 +306,57 @@ pub mod user {
client_async: reqwest::Client::new(),
})
}

pub fn create_session_cookie(credentials: &Credentials, id_token: String, duration: u64) -> Result<CreateSessionCookie, FirebaseError> {
let scope_list = vec![
"https://www.googleapis.com/auth/cloud-platform".to_string(),
"https://www.googleapis.com/auth/firebase.database".to_string(),
"https://www.googleapis.com/auth/firebase.messaging".to_string(),
"https://www.googleapis.com/auth/identitytoolkit".to_string(),
"https://www.googleapis.com/auth/userinfo.email".to_string(),
];

// Generate the assertion from the admin credentials
let iat = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
let assertion = encode(&Header::new(Algorithm::RS256),
&Claims {
scope: scope_list.join(" "),
aud: "https://accounts.google.com/o/oauth2/token".to_string(),
iat,
exp : iat + duration,
iss: credentials.client_email.to_string(),
},
&EncodingKey::from_rsa_pem(credentials.private_key.to_string().as_ref()).unwrap())
.unwrap();

// Request Google Oauth2 to retrieve the access token in order to create a session cookie
let client = reqwest::blocking::Client::new();
let google_oauth2_url = "https://accounts.google.com/o/oauth2/token".to_string();
let response_oauth2: Oauth2Response = client.post(&google_oauth2_url)
.form(&[("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"), ("assertion", &assertion)])
.send()
.unwrap()
.json()
.unwrap();

// Create a session cookie with the access token previously retrieved
let create_session_cookie_url: String = "https://identitytoolkit.googleapis.com/v1/projects/arenel:createSessionCookie".to_string();
let response_session_cookie_json: CreateSessionCookieResponseJson = client.post(&create_session_cookie_url)
.bearer_auth(&response_oauth2.access_token)
.json(&SessionLogin {
idToken: id_token,
validDuration: duration,
})
.send()
.unwrap()
.json()
.unwrap();


Ok(CreateSessionCookie {
session_cookie : response_session_cookie_json.sessionCookie
})
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions tests/sessions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use firestore_db_and_auth::*;
use firestore_db_and_auth::sessions::user::Session;
use std::fs;

#[test]
fn user_session_create_session_cookie() -> errors::Result<()> {
let cred = credentials::Credentials::from_file("firebase-service-account.json").expect("Read credentials file");
let id_token: String = fs::read_to_string("refresh-token-for-tests.txt")?;

println!("users::Session::create_session_cookie");
Session::create_session_cookie(&cred, id_token.to_string(), 3600)?;

Ok(())
}

0 comments on commit 2996fd0

Please sign in to comment.