send OIDC provider type as part of network config

Allows zeroidc to specify scopes based on provider as each provider implements the spec in their own special way sometimes
This commit is contained in:
Grant Limberg 2023-01-04 15:23:22 -08:00
commit ca6b91ff41
No known key found for this signature in database
GPG key ID: 8F2F97D3BE8D7735
5 changed files with 65 additions and 29 deletions

View file

@ -1246,6 +1246,11 @@ typedef struct
* oidc client id * oidc client id
*/ */
char ssoClientID[256]; char ssoClientID[256];
/**
* sso provider
**/
char ssoProvider[64];
} ZT_VirtualNetworkConfig; } ZT_VirtualNetworkConfig;
/** /**

View file

@ -1450,6 +1450,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
Utils::scopy(ec->ssoNonce, sizeof(ec->ssoNonce), _config.ssoNonce); Utils::scopy(ec->ssoNonce, sizeof(ec->ssoNonce), _config.ssoNonce);
Utils::scopy(ec->ssoState, sizeof(ec->ssoState), _config.ssoState); Utils::scopy(ec->ssoState, sizeof(ec->ssoState), _config.ssoState);
Utils::scopy(ec->ssoClientID, sizeof(ec->ssoClientID), _config.ssoClientID); Utils::scopy(ec->ssoClientID, sizeof(ec->ssoClientID), _config.ssoClientID);
Utils::scopy(ec->ssoProvider, sizeof(ec->ssoProvider), _config.ssoProvider);
} }
void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup) void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup)

View file

@ -302,10 +302,12 @@ public:
assert(_config.issuerURL != nullptr); assert(_config.issuerURL != nullptr);
assert(_config.ssoClientID != nullptr); assert(_config.ssoClientID != nullptr);
assert(_config.centralAuthURL != nullptr); assert(_config.centralAuthURL != nullptr);
assert(_config.ssoProvider != nullptr);
_idc = zeroidc::zeroidc_new( _idc = zeroidc::zeroidc_new(
_config.issuerURL, _config.issuerURL,
_config.ssoClientID, _config.ssoClientID,
_config.ssoProvider,
_config.centralAuthURL, _config.centralAuthURL,
_webPort _webPort
); );

View file

@ -28,6 +28,7 @@ pub extern "C" fn zeroidc_new(
issuer: *const c_char, issuer: *const c_char,
client_id: *const c_char, client_id: *const c_char,
auth_endpoint: *const c_char, auth_endpoint: *const c_char,
provider: *const c_char,
web_listen_port: u16, web_listen_port: u16,
) -> *mut ZeroIDC { ) -> *mut ZeroIDC {
if issuer.is_null() { if issuer.is_null() {
@ -40,6 +41,11 @@ pub extern "C" fn zeroidc_new(
return std::ptr::null_mut(); return std::ptr::null_mut();
} }
if provider.is_null() {
println!("provider is null");
return std::ptr::null_mut();
}
if auth_endpoint.is_null() { if auth_endpoint.is_null() {
println!("auth_endpoint is null"); println!("auth_endpoint is null");
return std::ptr::null_mut(); return std::ptr::null_mut();
@ -47,10 +53,12 @@ pub extern "C" fn zeroidc_new(
let issuer = unsafe { CStr::from_ptr(issuer) }; let issuer = unsafe { CStr::from_ptr(issuer) };
let client_id = unsafe { CStr::from_ptr(client_id) }; let client_id = unsafe { CStr::from_ptr(client_id) };
let provider = unsafe { CStr::from_ptr(provider) };
let auth_endpoint = unsafe { CStr::from_ptr(auth_endpoint) }; let auth_endpoint = unsafe { CStr::from_ptr(auth_endpoint) };
match ZeroIDC::new( match ZeroIDC::new(
issuer.to_str().unwrap(), issuer.to_str().unwrap(),
client_id.to_str().unwrap(), client_id.to_str().unwrap(),
provider.to_str().unwrap(),
auth_endpoint.to_str().unwrap(), auth_endpoint.to_str().unwrap(),
web_listen_port, web_listen_port,
) { ) {

View file

@ -61,6 +61,7 @@ struct Inner {
running: bool, running: bool,
issuer: String, issuer: String,
auth_endpoint: String, auth_endpoint: String,
provider: String,
oidc_thread: Option<JoinHandle<()>>, oidc_thread: Option<JoinHandle<()>>,
oidc_client: Option<openidconnect::core::CoreClient>, oidc_client: Option<openidconnect::core::CoreClient>,
access_token: Option<AccessToken>, access_token: Option<AccessToken>,
@ -115,6 +116,7 @@ impl ZeroIDC {
pub fn new( pub fn new(
issuer: &str, issuer: &str,
client_id: &str, client_id: &str,
provider: &str,
auth_ep: &str, auth_ep: &str,
local_web_port: u16, local_web_port: u16,
) -> Result<ZeroIDC, ZeroIDCError> { ) -> Result<ZeroIDC, ZeroIDCError> {
@ -122,6 +124,7 @@ impl ZeroIDC {
inner: Arc::new(Mutex::new(Inner { inner: Arc::new(Mutex::new(Inner {
running: false, running: false,
issuer: issuer.to_string(), issuer: issuer.to_string(),
provider: provider.to_string(),
auth_endpoint: auth_ep.to_string(), auth_endpoint: auth_ep.to_string(),
oidc_thread: None, oidc_thread: None,
oidc_client: None, oidc_client: None,
@ -444,36 +447,53 @@ impl ZeroIDC {
if need_verifier || csrf_diff || nonce_diff { if need_verifier || csrf_diff || nonce_diff {
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256(); let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
let r = i.oidc_client.as_ref().map(|c| { let r = i.oidc_client.as_ref().map(|c| {
if i.issuer.contains("okta") { let mut auth_builder = c
let (auth_url, csrf_token, nonce) = c .authorize_url(
.authorize_url( AuthenticationFlow::<CoreResponseType>::AuthorizationCode,
AuthenticationFlow::<CoreResponseType>::AuthorizationCode, csrf_func(csrf_token),
csrf_func(csrf_token), nonce_func(nonce),
nonce_func(nonce), )
) .set_pkce_challenge(pkce_challenge);
.add_scope(Scope::new("profile".to_string())) match i.provider.as_str() {
.add_scope(Scope::new("email".to_string())) "auth0" => {
.add_scope(Scope::new("offline_access".to_string())) auth_builder = auth_builder
.add_scope(Scope::new("groups".to_string())) .add_scope(Scope::new("profile".to_string()))
.set_pkce_challenge(pkce_challenge) .add_scope(Scope::new("email".to_string()))
.url(); .add_scope(Scope::new("offline_access".to_string()));
}
(auth_url, csrf_token, nonce) "okta" => {
} else { auth_builder = auth_builder
let (auth_url, csrf_token, nonce) = c .add_scope(Scope::new("profile".to_string()))
.authorize_url( .add_scope(Scope::new("email".to_string()))
AuthenticationFlow::<CoreResponseType>::AuthorizationCode, .add_scope(Scope::new("groups".to_string()))
csrf_func(csrf_token), .add_scope(Scope::new("offline_access".to_string()));
nonce_func(nonce), }
) "keycloak" => {
.add_scope(Scope::new("profile".to_string())) auth_builder = auth_builder
.add_scope(Scope::new("email".to_string())) .add_scope(Scope::new("profile".to_string()))
.add_scope(Scope::new("offline_access".to_string())) .add_scope(Scope::new("email".to_string()));
.set_pkce_challenge(pkce_challenge) }
.url(); "onelogin" => {
auth_builder = auth_builder
(auth_url, csrf_token, nonce) .add_scope(Scope::new("profile".to_string()))
.add_scope(Scope::new("email".to_string()))
.add_scope(Scope::new("groups".to_string()))
}
"default" => {
auth_builder = auth_builder
.add_scope(Scope::new("profile".to_string()))
.add_scope(Scope::new("email".to_string()))
.add_scope(Scope::new("offline_access".to_string()));
}
_ => {
auth_builder = auth_builder
.add_scope(Scope::new("profile".to_string()))
.add_scope(Scope::new("email".to_string()))
.add_scope(Scope::new("offline_access".to_string()));
}
} }
auth_builder.url()
}); });
if let Some(r) = r { if let Some(r) = r {