Difference between revisions of "HowTo:Integrate UBIK in an SSO Environment"
(→Interfacing) |
(→Important information) |
||
(18 intermediate revisions by the same user not shown) | |||
Line 6: | Line 6: | ||
= Instructions = | = Instructions = | ||
+ | |||
+ | == Important information == | ||
+ | Single Sign-On (SSO) offers benefits beyond reusing a central account, such as ensuring only the identity provider and browser see user credentials, and enforcing two-factor authentication (2FA). Organizations often secure HTTPS interactions by ensuring requests carry a session cookie from the identity provider or redirecting requests to the identity provider. | ||
+ | |||
+ | While this works for web applications in browsers, it poses challenges for non-browser applications like daemon services or mobile apps. UBIK® addresses this by requiring a valid SSO login via a web browser to create session tokens for its own back channels, making interception by an application gateway not only ineffective but also problematic, as it prevents UBIK® from functioning. Therefore, UBIK® web service URLs must be excluded from 2FA rules on the application gateway to implement SSO securely. | ||
+ | |||
+ | {{Hint|It is necessary to exclude {{UBIK}} web service URLs from any application gateway's 2FA redirect rules!}} | ||
+ | |||
+ | Concerns about breaching cybersecurity protocols are unfounded, as UBIK® ensures all sessions are secured via the identity provider. The responsibility for securing the back channel lies with UBIK®, as it is not a web application. | ||
+ | |||
+ | If there are further questions, support is available to help. | ||
+ | |||
+ | [[Category:How-To|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:SSO|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:Version 3.6|Integrate UBIK in an SSO Environment]] | ||
== Login == | == Login == | ||
Line 20: | Line 35: | ||
* On the server side, make sure that an SSO Processor is configured able to process the responses from the IdP. Also, the processor can be customized for managing the login in greater detail and according to the project's requirements. | * On the server side, make sure that an SSO Processor is configured able to process the responses from the IdP. Also, the processor can be customized for managing the login in greater detail and according to the project's requirements. | ||
− | == Interfacing == | + | == Interfacing with SSO == |
− | When a {{UBIK}} object is synchronized between client and server, the {{UBIK}} customizing can interact with external systems. There, we might require | + | When a {{UBIK}} object is synchronized between client and server, the {{UBIK}} customizing can interact with external systems. There, we might require authentication, and we need the user to provide a respective token so we can act on their behalf. In order to do so, we have to clarify the following details: |
− | * For which types of objects (meta classes) do I need to interact with external systems, requiring SSO | + | * For which types of objects (meta classes) do I need to interact with external systems, requiring SSO authentication? |
− | * For which synchronization operations (e.g., update, commit, create, etc.) do I need | + | * For which synchronization operations (e.g., update, commit, create, etc.) do I need authentication? |
* Which SSO client configurations (identity provider base URL, scopes, etc. - see "login") are used in this case? | * Which SSO client configurations (identity provider base URL, scopes, etc. - see "login") are used in this case? | ||
For each resulting combination we have to create an [[SYSCLS_EXTERNALAUTHCONFIG|External Auth Config]] object and give it to the client in the infrastructure list. | For each resulting combination we have to create an [[SYSCLS_EXTERNALAUTHCONFIG|External Auth Config]] object and give it to the client in the infrastructure list. | ||
− | Further, we have to make sure the | + | Further, we have to make sure the authentication tokens can be transported to the server. Therefore, add the [[SYSCLS_EXTERNALENTITY|External Entity Classification]] to all meta classes of objects that need external authentication. |
With this, the {{UBIK}} session in the web service's {{UBIK}} Environment is tagged with the SSO token, and the customizing code can use it to interact with 3rd party systems. | With this, the {{UBIK}} session in the web service's {{UBIK}} Environment is tagged with the SSO token, and the customizing code can use it to interact with 3rd party systems. | ||
− | + | ||
− | + | ||
− | + | ||
= Studio = | = Studio = | ||
Line 39: | Line 54: | ||
== Login == | == Login == | ||
* Install the Auth Processor plugin (SAMLProcessor or OIDCProcessor plugin) in your web service's injection folder | * Install the Auth Processor plugin (SAMLProcessor or OIDCProcessor plugin) in your web service's injection folder | ||
− | * Customize your UBIK Context, overriding the method "GetSSOProcessor" so it returns an instance of the authentication processor | + | * Customize your UBIK Context, overriding the method "GetSSOProcessor" so it returns an instance of the authentication processor |
− | + | === Applying an SSO Processor === | |
+ | <div class="toccolours mw-collapsible mw-collapsed" style="width:100%; overflow:auto;"> | ||
+ | <div style="font-weight:bold;line-height:1.6;">OIDC</div> | ||
+ | <div class="mw-collapsible-content"> | ||
{{Version/ServerSince|4.6.0}}In the case of a periodic rolling of the signing key, use the DynamicOIDCProcessor which fetches the JWKS automatically via the base URL of the chosen OIDC Provider: | {{Version/ServerSince|4.6.0}}In the case of a periodic rolling of the signing key, use the DynamicOIDCProcessor which fetches the JWKS automatically via the base URL of the chosen OIDC Provider: | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
Line 71: | Line 89: | ||
You will need to insert the correct jwks from your OIDC Provider instead of "...". | You will need to insert the correct jwks from your OIDC Provider instead of "...". | ||
− | + | </div></div> | |
− | <syntaxhighlight lang="csharp"> | + | |
+ | <div class="toccolours mw-collapsible mw-collapsed" style="width:100%; overflow:auto;"> | ||
+ | <div style="font-weight:bold;line-height:1.6;">SAML</div> | ||
+ | <div class="mw-collapsible-content"> | ||
+ | <syntaxhighlight lang="csharp"> | ||
public override UBIK.Kernel.SSO.ISSOProcessor GetSSOProcessor(System.String token) | public override UBIK.Kernel.SSO.ISSOProcessor GetSSOProcessor(System.String token) | ||
{ | { | ||
Line 85: | Line 107: | ||
You will need to load the correct certificate from your SAML Identity Provider instead of null. It's recommended to save the certificate on the server and load it from file storage. The certificate must be the one the IdP uses to sign its SAML responses with. | You will need to load the correct certificate from your SAML Identity Provider instead of null. It's recommended to save the certificate on the server and load it from file storage. The certificate must be the one the IdP uses to sign its SAML responses with. | ||
− | == Customizing the SSO processor == | + | </div></div> |
+ | |||
+ | === Customizing the SSO processor === | ||
There are several use-cases where we need to customize the SSO processor. We can define what should be done when a login object is required or found, and we can use the information delivered with the SSO token in the form of assertions or claims. In any case, we must override the SSO processor implementation, e.g.: | There are several use-cases where we need to customize the SSO processor. We can define what should be done when a login object is required or found, and we can use the information delivered with the SSO token in the form of assertions or claims. In any case, we must override the SSO processor implementation, e.g.: | ||
− | <syntaxhighlight lang="csharp"> | + | <div class="toccolours mw-collapsible mw-collapsed" style="width:100%; overflow:auto;"> |
− | public class MyOIDCProcessor : DynamicOIDCProcessorExt | + | <div style="font-weight:bold;line-height:1.6;">Example Code</div> |
+ | <div class="mw-collapsible-content"> | ||
+ | <syntaxhighlight lang="csharp" > | ||
+ | public class MyOIDCProcessor : UBIK.SSO.OIDCProcessor.DynamicOIDCProcessorExt | ||
{ | { | ||
// Example for a claim type identifier used to get a value from the Assertions() dictionary. | // Example for a claim type identifier used to get a value from the Assertions() dictionary. | ||
Line 98: | Line 125: | ||
{ } | { } | ||
− | protected override Login CreateLogin(string loginName, string domain, OSTypes osType) | + | protected override Login CreateLogin(string loginName, string domain, UBIK.Service.DTO.V220.OSTypes osType) |
{ | { | ||
// In this example, we use the default login creation, but add the email address as the human-readable login name. | // In this example, we use the default login creation, but add the email address as the human-readable login name. | ||
Line 106: | Line 133: | ||
// The Assertions() method yields a Dictionary<string, object>, where the values usually are strings, too. | // The Assertions() method yields a Dictionary<string, object>, where the values usually are strings, too. | ||
// The keys correspond to the claim type identifiers. | // The keys correspond to the claim type identifiers. | ||
− | if (Assertions().ContainsKey( | + | if (Assertions().ContainsKey(KEY_MAIL) && !string.IsNullOrEmpty(Assertions()[KEY_MAIL] as string)) |
{ | { | ||
− | login.Name = Assertions()[ | + | login.Name = Assertions()[KEY_MAIL] as string; |
UBIKKernel.LogCustomizing(MethodBase.GetCurrentMethod(), | UBIKKernel.LogCustomizing(MethodBase.GetCurrentMethod(), | ||
$"Login name for {login.ID} was set to {login.Name} -> Key: {KEY_MAIL}"); | $"Login name for {login.ID} was set to {login.Name} -> Key: {KEY_MAIL}"); | ||
Line 127: | Line 154: | ||
{ | { | ||
// Here, we could update groups assignment or other account information. | // Here, we could update groups assignment or other account information. | ||
+ | // If the login object is modified here, please remember to call the login.Save() method before returning! | ||
} | } | ||
return login; | return login; | ||
Line 138: | Line 166: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | </div></div> | ||
+ | |||
+ | [[Category:How-To|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:SSO|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:Version 3.6|Integrate UBIK in an SSO Environment]] | ||
== Interfacing == | == Interfacing == | ||
Line 149: | Line 183: | ||
public string GetOIDCToken(UBIKSession session, BaseClass c, UBIK.Kernel.Classification.SSO.IOOperation op) | public string GetOIDCToken(UBIKSession session, BaseClass c, UBIK.Kernel.Classification.SSO.IOOperation op) | ||
{ | { | ||
− | UBIKKernel.LogDebugOutput(MethodBase.GetCurrentMethod(), 1234, | + | UBIKKernel.LogDebugOutput(MethodBase.GetCurrentMethod(), 1234, "Getting OIDC Token", this); |
UBIK.Kernel.Classification.SSO.SSOCacheKey key = new UBIK.Kernel.Classification.SSO.SSOCacheKey(op, c.ClassID); | UBIK.Kernel.Classification.SSO.SSOCacheKey key = new UBIK.Kernel.Classification.SSO.SSOCacheKey(op, c.ClassID); | ||
if (session.Tags.TryRetrieveTag(key, out object tag)) | if (session.Tags.TryRetrieveTag(key, out object tag)) | ||
Line 164: | Line 198: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | ||
− | + | ||
− | + | ||
= Client = | = Client = | ||
Line 173: | Line 207: | ||
* Set up an identity provider if necessary | * Set up an identity provider if necessary | ||
− | * Assemble a client configuration JSON string, .e.g.: | + | * Assemble a client configuration JSON string, .e.g. for Entra: |
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
− | {'AuthorityURL' : 'https:// | + | {'AuthorityURL' : 'https://login.microsoftonline.com/{tenantid}/v2.0', |
− | 'ClientID' : ' | + | 'ClientID' : '{clientid}', |
'ClientSecret' : null, | 'ClientSecret' : null, | ||
'RedirectURL' : 'com.augmensys.ubik://SSO', | 'RedirectURL' : 'com.augmensys.ubik://SSO', | ||
Line 192: | Line 226: | ||
</InternalSSOSettings> | </InternalSSOSettings> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | {{Hint|Entra requires a client secret for web applications (to be configured both in Entra as well as in the client profile's OIDC settings described above). For native/mobile applications, the client secret must be null though!}} | ||
+ | |||
+ | [[Category:How-To|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:SSO|Integrate UBIK in an SSO Environment]] | ||
+ | [[Category:Version 3.6|Integrate UBIK in an SSO Environment]] | ||
== SAML == | == SAML == |
Latest revision as of 07:33, 9 October 2024
Single Sign-On (SSO) allows an end-user to interact with multiple services without logging in more than once.
This page shows how to integrate UBIK® into such an SSO environment.