Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions src/canister_tests/src/api/internet_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,34 @@ pub fn config(
call_candid(env, canister_id, RawEffectivePrincipal::None, "config", ()).map(|(x,)| x)
}

pub fn discovered_oidc_configs(
env: &PocketIc,
canister_id: CanisterId,
) -> Result<Vec<types::OidcConfig>, RejectResponse> {
call_candid(
env,
canister_id,
RawEffectivePrincipal::None,
"discovered_oidc_configs",
(),
)
.map(|(x,)| x)
}

pub fn add_discoverable_oidc_config(
env: &PocketIc,
canister_id: CanisterId,
config: types::DiscoverableOidcConfig,
) -> Result<(), RejectResponse> {
call_candid(
env,
canister_id,
RawEffectivePrincipal::None,
"add_discoverable_oidc_config",
(config,),
)
}

pub fn openid_prepare_delegation(
env: &PocketIc,
canister_id: CanisterId,
Expand Down
1 change: 1 addition & 0 deletions src/internet_identity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ captcha = { git = "https://github.com/dfinity/captcha", rev = "9c0d2dd9bf519e255

# OpenID deps
identity_jose = { git = "https://github.com/dfinity/identity.rs.git", rev = "aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8", default-features = false }
url = { version = "2.5", default-features = false, features = ["std"] }

# All IC deps
candid.workspace = true
Expand Down
25 changes: 25 additions & 0 deletions src/internet_identity/internet_identity.did
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ type InternetIdentityInit = record {
new_flow_origins : opt vec text;
// Configurations for OpenID clients
openid_configs : opt vec OpenIdConfig;
// Deprecated in init args: use add_discoverable_oidc_config update call instead.
// Kept for backward compatibility and config() query output.
oidc_configs : opt vec DiscoverableOidcConfig;
Comment thread
sea-snake marked this conversation as resolved.
// Configuration for Web Analytics
analytics_config : opt opt AnalyticsConfig;
// Configuration to show dapps explorer or not
Expand Down Expand Up @@ -383,6 +386,23 @@ type OpenIdConfig = record {
email_verification : opt OpenIdEmailVerification;
};

// SSO provider config that uses two-hop discovery.
// The backend fetches https://{discovery_domain}/.well-known/ii-openid-configuration
// for { client_id, openid_configuration } and then fetches the standard OIDC
// discovery at openid_configuration for { issuer, jwks_uri }.
type DiscoverableOidcConfig = record {
discovery_domain : text;
};

// Resolved SSO provider state.
// All fields other than discovery_domain are None until discovery completes.
type OidcConfig = record {
discovery_domain : text;
client_id : opt text;
openid_configuration : opt text;
issuer : opt text;
};

type OpenIdCredentialKey = record { Iss; Sub };

type AnalyticsConfig = variant {
Expand Down Expand Up @@ -1175,6 +1195,11 @@ service : (opt InternetIdentityInit) -> {
// =====================
http_request : (request : HttpRequest) -> (HttpResponse) query;

// OIDC Discovery
// ===============
discovered_oidc_configs : () -> (vec OidcConfig) query;
add_discoverable_oidc_config : (DiscoverableOidcConfig) -> ();

// Internal Methods
// ================
init_salt : () -> ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,14 @@ fn create_openid_credential_and_config(
let OpenIDRegFinishArg { jwt, salt, name: _ } = openid_registration_data;

let (openid_credential, openid_config_iss) = openid::with_provider(jwt, |provider| {
Ok((provider.verify(jwt, salt)?, provider.issuer()))
// `with_provider` only yields providers whose discovery has completed, so
// `issuer()` is always Some — surface an explicit error if that ever breaks.
let issuer = provider.issuer().ok_or_else(|| {
openid::OpenIDJWTVerificationError::GenericError(
"Selected provider has no issuer after discovery filter".to_string(),
)
})?;
Ok((provider.verify(jwt, salt)?, issuer))
})?;

Ok((openid_credential, openid_config_iss))
Expand Down
22 changes: 18 additions & 4 deletions src/internet_identity/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,16 @@ fn stats() -> InternetIdentityStats {
})
}

#[query]
fn discovered_oidc_configs() -> Vec<OidcConfig> {
openid::get_discovered_oidc_configs()
}

#[update]
fn add_discoverable_oidc_config(config: DiscoverableOidcConfig) {
openid::add_oidc_config(config);
}

#[query]
fn config() -> InternetIdentityInit {
let archive_config = match state::archive_state() {
Expand All @@ -568,6 +578,7 @@ fn config() -> InternetIdentityInit {
related_origins: persistent_state.related_origins.clone(),
new_flow_origins: persistent_state.new_flow_origins.clone(),
openid_configs: persistent_state.openid_configs.clone(),
oidc_configs: persistent_state.oidc_configs.clone(),
Comment thread
sea-snake marked this conversation as resolved.
analytics_config: Some(persistent_state.analytics_config.clone()),
enable_dapps_explorer: persistent_state.enable_dapps_explorer,
is_production: persistent_state.is_production,
Expand Down Expand Up @@ -625,6 +636,9 @@ fn initialize(maybe_arg: Option<InternetIdentityInit>) {
if let Some(openid_configs) = config.openid_configs {
openid::setup(openid_configs);
}
if let Some(oidc_configs) = config.oidc_configs {
openid::setup_oidc(oidc_configs);
}
}

fn apply_install_arg(maybe_arg: Option<InternetIdentityInit>) {
Expand Down Expand Up @@ -657,14 +671,14 @@ fn apply_install_arg(maybe_arg: Option<InternetIdentityInit>) {
persistent_state.related_origins = Some(related_origins);
})
}
if let Some(new_flow_origins) = arg.new_flow_origins {
if let Some(openid_configs) = arg.openid_configs {
state::persistent_state_mut(|persistent_state| {
persistent_state.new_flow_origins = Some(new_flow_origins);
persistent_state.openid_configs = Some(openid_configs);
})
}
if let Some(openid_configs) = arg.openid_configs {
if let Some(new_flow_origins) = arg.new_flow_origins {
state::persistent_state_mut(|persistent_state| {
persistent_state.openid_configs = Some(openid_configs);
persistent_state.new_flow_origins = Some(new_flow_origins);
})
}
if let Some(analytics_config) = arg.analytics_config {
Expand Down
Loading
Loading