Skip to content

Commit 4e62fb4

Browse files
committed
add tests for allow_existing_users: false
1 parent 3ba09b0 commit 4e62fb4

File tree

1 file changed

+163
-0
lines changed
  • crates/handlers/src/upstream_oauth2

1 file changed

+163
-0
lines changed

crates/handlers/src/upstream_oauth2/link.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,4 +1326,167 @@ mod tests {
13261326

13271327
assert_eq!(email.email, oidc_email);
13281328
}
1329+
1330+
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
1331+
async fn test_link_existing_account_when_not_allowed(pool: PgPool) {
1332+
#[allow(clippy::disallowed_methods)]
1333+
let timestamp = chrono::Utc::now().timestamp_millis();
1334+
1335+
//suffix timestamp to generate unique test data
1336+
let existing_username = format!("{}{}", "john",timestamp);
1337+
let existing_email = format!("{}@{}", existing_username, "example.com");
1338+
1339+
//existing username matches oidc username
1340+
let oidc_username = existing_username.clone();
1341+
1342+
//oidc email is different from existing email
1343+
let oidc_email: String = format!("{}{}@{}", "any_email", timestamp,"example.com");
1344+
1345+
let subject = format!("{}+{}", "subject", timestamp);
1346+
1347+
setup();
1348+
let state = TestState::from_pool(pool).await.unwrap();
1349+
let mut rng = state.rng();
1350+
let cookies = CookieHelper::new();
1351+
1352+
let claims_imports = UpstreamOAuthProviderClaimsImports {
1353+
localpart: UpstreamOAuthProviderImportPreference {
1354+
action: mas_data_model::UpstreamOAuthProviderImportAction::Require,
1355+
template: None,
1356+
},
1357+
email: UpstreamOAuthProviderImportPreference {
1358+
action: mas_data_model::UpstreamOAuthProviderImportAction::Require,
1359+
template: None,
1360+
},
1361+
..UpstreamOAuthProviderClaimsImports::default()
1362+
};
1363+
1364+
let id_token = serde_json::json!({
1365+
"preferred_username": oidc_username,
1366+
"email": oidc_email,
1367+
"email_verified": true,
1368+
});
1369+
1370+
// Grab a key to sign the id_token
1371+
// We could generate a key on the fly, but because we have one available here,
1372+
// why not use it?
1373+
let key = state
1374+
.key_store
1375+
.signing_key_for_algorithm(&JsonWebSignatureAlg::Rs256)
1376+
.unwrap();
1377+
1378+
let signer = key
1379+
.params()
1380+
.signing_key_for_alg(&JsonWebSignatureAlg::Rs256)
1381+
.unwrap();
1382+
let header = JsonWebSignatureHeader::new(JsonWebSignatureAlg::Rs256);
1383+
let id_token = Jwt::sign_with_rng(&mut rng, header, id_token, &signer).unwrap();
1384+
1385+
// Provision a provider and a link
1386+
let mut repo = state.repository().await.unwrap();
1387+
let provider = repo
1388+
.upstream_oauth_provider()
1389+
.add(
1390+
&mut rng,
1391+
&state.clock,
1392+
UpstreamOAuthProviderParams {
1393+
issuer: Some("https://example.com/".to_owned()),
1394+
human_name: Some("Example Ltd.".to_owned()),
1395+
brand_name: None,
1396+
scope: Scope::from_iter([OPENID]),
1397+
token_endpoint_auth_method: UpstreamOAuthProviderTokenAuthMethod::None,
1398+
token_endpoint_signing_alg: None,
1399+
id_token_signed_response_alg: JsonWebSignatureAlg::Rs256,
1400+
client_id: "client".to_owned(),
1401+
encrypted_client_secret: None,
1402+
claims_imports,
1403+
authorization_endpoint_override: None,
1404+
token_endpoint_override: None,
1405+
userinfo_endpoint_override: None,
1406+
fetch_userinfo: false,
1407+
userinfo_signed_response_alg: None,
1408+
jwks_uri_override: None,
1409+
discovery_mode: mas_data_model::UpstreamOAuthProviderDiscoveryMode::Oidc,
1410+
pkce_mode: mas_data_model::UpstreamOAuthProviderPkceMode::Auto,
1411+
response_mode: None,
1412+
allow_existing_users: false,
1413+
additional_authorization_parameters: Vec::new(),
1414+
forward_login_hint: false,
1415+
ui_order: 0,
1416+
},
1417+
)
1418+
.await
1419+
.unwrap();
1420+
1421+
let session = repo
1422+
.upstream_oauth_session()
1423+
.add(
1424+
&mut rng,
1425+
&state.clock,
1426+
&provider,
1427+
"state".to_owned(),
1428+
None,
1429+
Some("nonce".to_owned()),
1430+
)
1431+
.await
1432+
.unwrap();
1433+
1434+
let link = repo
1435+
.upstream_oauth_link()
1436+
.add(
1437+
&mut rng,
1438+
&state.clock,
1439+
&provider,
1440+
subject.clone(),
1441+
None,
1442+
)
1443+
.await
1444+
.unwrap();
1445+
1446+
let session = repo
1447+
.upstream_oauth_session()
1448+
.complete_with_link(
1449+
&state.clock,
1450+
session,
1451+
&link,
1452+
Some(id_token.into_string()),
1453+
None,
1454+
None,
1455+
)
1456+
.await
1457+
.unwrap();
1458+
1459+
//create a user with an email
1460+
let user = repo
1461+
.user()
1462+
.add(&mut rng, &state.clock, existing_username.clone())
1463+
.await
1464+
.unwrap();
1465+
1466+
let _user_email = repo
1467+
.user_email()
1468+
.add(&mut rng, &state.clock, &user, existing_email.clone())
1469+
.await;
1470+
1471+
repo.save().await.unwrap();
1472+
1473+
let cookie_jar = state.cookie_jar();
1474+
let upstream_sessions = UpstreamSessionsCookie::default()
1475+
.add(session.id, provider.id, "state".to_owned(), None)
1476+
.add_link_to_session(session.id, link.id)
1477+
.unwrap();
1478+
let cookie_jar = upstream_sessions.save(cookie_jar, &state.clock);
1479+
cookies.import(cookie_jar);
1480+
1481+
let request = Request::get(&*mas_router::UpstreamOAuth2Link::new(link.id).path()).empty();
1482+
let request = cookies.with_cookies(request);
1483+
let response = state.request(request).await;
1484+
cookies.save_cookies(&response);
1485+
response.assert_status(StatusCode::OK);
1486+
response.assert_header_value(CONTENT_TYPE, "text/html; charset=utf-8");
1487+
1488+
assert!(response
1489+
.body().contains("Unexpected error"));
1490+
1491+
}
13291492
}

0 commit comments

Comments
 (0)