Skip to content

Commit 4c3cf36

Browse files
committed
controllers/session: Save GitHub access tokens in encrypted form too
1 parent b011bb0 commit 4c3cf36

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed

src/controllers/session.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use minijinja::context;
1919
use oauth2::{AuthorizationCode, CsrfToken, Scope, TokenResponse};
2020
use secrecy::ExposeSecret;
2121
use serde::{Deserialize, Serialize};
22-
use tracing::warn;
22+
use tracing::{error, warn};
2323

2424
#[derive(Debug, Serialize, utoipa::ToSchema)]
2525
pub struct BeginResponse {
@@ -114,11 +114,25 @@ pub async fn authorize_session(
114114

115115
let token = token.access_token();
116116

117+
// Encrypt the GitHub access token
118+
let encryption = &app.config.gh_token_encryption;
119+
let encrypted_token = encryption.encrypt(token.secret()).map_err(|error| {
120+
error!("Failed to encrypt GitHub token: {error}");
121+
server_error("Internal server error")
122+
})?;
123+
117124
// Fetch the user info from GitHub using the access token we just got and create a user record
118125
let ghuser = app.github.current_user(token).await?;
119126

120127
let mut conn = app.db_write().await?;
121-
let user = save_user_to_database(&ghuser, token.secret(), &app.emails, &mut conn).await?;
128+
let user = save_user_to_database(
129+
&ghuser,
130+
token.secret(),
131+
&encrypted_token,
132+
&app.emails,
133+
&mut conn,
134+
)
135+
.await?;
122136

123137
// Log in by setting a cookie and the middleware authentication
124138
session.insert("user_id".to_string(), user.id.to_string());
@@ -129,6 +143,7 @@ pub async fn authorize_session(
129143
pub async fn save_user_to_database(
130144
user: &GitHubUser,
131145
access_token: &str,
146+
encrypted_token: &[u8],
132147
emails: &Emails,
133148
conn: &mut AsyncPgConnection,
134149
) -> QueryResult<User> {
@@ -138,6 +153,7 @@ pub async fn save_user_to_database(
138153
.maybe_name(user.name.as_deref())
139154
.maybe_gh_avatar(user.avatar_url.as_deref())
140155
.gh_access_token(access_token)
156+
.gh_encrypted_token(encrypted_token)
141157
.build();
142158

143159
match create_or_update_user(&new_user, user.email.as_deref(), emails, conn).await {
@@ -242,7 +258,9 @@ mod tests {
242258
id: -1,
243259
avatar_url: None,
244260
};
245-
let result = save_user_to_database(&gh_user, "arbitrary_token", &emails, &mut conn).await;
261+
262+
let result =
263+
save_user_to_database(&gh_user, "arbitrary_token", &[], &emails, &mut conn).await;
246264

247265
assert!(
248266
result.is_ok(),

src/tests/user.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async fn updating_existing_user_doesnt_change_api_token() -> anyhow::Result<()>
3838
email: None,
3939
avatar_url: None,
4040
};
41-
assert_ok!(session::save_user_to_database(&gh_user, "bar_token", emails, &mut conn).await);
41+
assert_ok!(session::save_user_to_database(&gh_user, "bar_token", &[], emails, &mut conn).await);
4242

4343
// Use the original API token to find the now updated user
4444
let hashed_token = assert_ok!(HashedToken::parse(token));
@@ -79,8 +79,8 @@ async fn github_without_email_does_not_overwrite_email() -> anyhow::Result<()> {
7979
avatar_url: None,
8080
};
8181

82-
let u =
83-
session::save_user_to_database(&gh_user, "some random token", emails, &mut conn).await?;
82+
let u = session::save_user_to_database(&gh_user, "some random token", &[], emails, &mut conn)
83+
.await?;
8484

8585
let user_without_github_email = MockCookieUser::new(&app, u);
8686

@@ -103,8 +103,8 @@ async fn github_without_email_does_not_overwrite_email() -> anyhow::Result<()> {
103103
avatar_url: None,
104104
};
105105

106-
let u =
107-
session::save_user_to_database(&gh_user, "some random token", emails, &mut conn).await?;
106+
let u = session::save_user_to_database(&gh_user, "some random token", &[], emails, &mut conn)
107+
.await?;
108108

109109
let again_user_without_github_email = MockCookieUser::new(&app, u);
110110

@@ -145,8 +145,8 @@ async fn github_with_email_does_not_overwrite_email() -> anyhow::Result<()> {
145145
avatar_url: None,
146146
};
147147

148-
let u =
149-
session::save_user_to_database(&gh_user, "some random token", &emails, &mut conn).await?;
148+
let u = session::save_user_to_database(&gh_user, "some random token", &[], &emails, &mut conn)
149+
.await?;
150150

151151
let user_with_different_email_in_github = MockCookieUser::new(&app, u);
152152

@@ -202,8 +202,8 @@ async fn test_confirm_user_email() -> anyhow::Result<()> {
202202
avatar_url: None,
203203
};
204204

205-
let u =
206-
session::save_user_to_database(&gh_user, "some random token", emails, &mut conn).await?;
205+
let u = session::save_user_to_database(&gh_user, "some random token", &[], emails, &mut conn)
206+
.await?;
207207

208208
let user = MockCookieUser::new(&app, u);
209209
let user_model = user.as_model();
@@ -248,8 +248,8 @@ async fn test_existing_user_email() -> anyhow::Result<()> {
248248
avatar_url: None,
249249
};
250250

251-
let u =
252-
session::save_user_to_database(&gh_user, "some random token", emails, &mut conn).await?;
251+
let u = session::save_user_to_database(&gh_user, "some random token", &[], emails, &mut conn)
252+
.await?;
253253

254254
update(Email::belonging_to(&u))
255255
// Users created before we added verification will have

0 commit comments

Comments
 (0)