Using OpenACS with External Identity Providers
With the forthcoming version, OpenACS 5.10.1 (and the current head version in the oacs-5-10 branch) OpenACS provides support for external identity providers, which can be used in parallel to the existing OpenACS authorities. It is possible, that users can
- login alternatively via the configured authority and/or via external identity providers, or
- exclusively over external identity providers
The alternative login requires that the same email address is used for a user in OpenACS and on the identity provider.
Handling of unregistered users
When using alternative logins, the returned user information might match pre-existing OpenACS users, or user information, which is unknown to the system. In such a situation, three scenarios might be possible:
- reject the unknown user
- create a new OpenACS user based on the information returned from the identity provider.
The default behavior of the implementation is to reject the user. When the optional flag "-create_not_registered_users" is activated for an external provider, such users will be created. When creating users (e.g. in dotlrn), it is also possible to add these automatically to certain dotlrn groups (specified in "create_with_dotlrn_role"). Further behavior might be specified by extending the predefined behavior (see example below).
Supported external identity providers for alternative logins
Currently, the following (OAuth 2 based) identity providers are supported
- Microsoft Identity Platform (based on ID-Tokens) based on Azure and Active Directory
- GitHub
OpenACS allows defining one or more identity handlers by defining either different login-handler objects for the same identity provider (e.g. for use on different subsites) to by defining login-handler objects for different identity providers (maybe also for the same subsite).
To enable the external identity providers, the package xooauth has to be installed and one or more external identity providers must be configured on the side of the provider service (to allow its usage for the OpenACS instance) and on the OpenACS instance. So, make sure xooauth is installed and mounted on /oauth (the mount path is relevant for the Redirect URI below).
Microsoft Identity Platform
- Configuration on the provider side:
- Register application via the Azure Portal
- Set the Redirect URI type to Web and value pointing to the redirect page (e.g. YOURLOCATION/oauth/www/azure-login-handler)
- In this process you will obtain the "tenant_id", "client_id" and a "client_secret"
- Microsoft supports its ID token interface in version v1.0 and v2.0. When v2.0 is configured on the OpenACS side (see below), make sure to define in the "Token configuration" the optional claims "upn", "family_name", and "given_name" (latter two only, when allowing automatic account creation).
- Details: Add sign-in with Microsoft to a web app, Microsoft identity platform ID tokens
- Configuration on OpenACS
- Create a login-handler object (e.g. in xooauth/tcl/oauth-init.tcl)
ms::Authorize create ms::azure -tenant "..." \ -client_id "..."
Potential further parameters:
-responder_url "..." (default "/oauth/azure-login-handler")
-debug
-create_not_registered_users
-create_with_dotlrn_role "..."
-after_successful_login_url "..."
-login_failure_url "..."
- The interface is based on the same infrastructure as the Microsoft Graph interface of OpenACS.
- For the full list of parameters, see the online documentation of the ms::Authorize class.
- Create a login-handler object (e.g. in xooauth/tcl/oauth-init.tcl)
Using GitHub as Identity Provider
- Configuration on the provider side:
- Register application on GitHub: login on GitHub (with e.g. your ID), goto "Settings", "Developer Settings", "OAuth Apps", "Register a new application"
- Set the Redirect URI: When registering the application, fill in the value of "Authorization callback URL" to YOURLOCATION/oauth/www/github-login-handler
- Details: Authorizing OAuth Apps
- Configuration on OpenACS
- Create a login-handler object (e.g. in xooauth/tcl/oauth-init.tcl)
xo::oauth::GitHub create ::xo::oauth::github \ -client_id "..." \ -client_secret "..."
Potential further parameters:
-responder_url "..." (default "/oauth/github-login-handler")
-debug
-create_not_registered_users
-create_with_dotlrn_role "..."
-after_successful_login_url "..."
-login_failure_url "..." - For the full list of parameters, see the online documentation of the GitHub class.
- Create a login-handler object (e.g. in xooauth/tcl/oauth-init.tcl)
The parameters "-debug", "-create_not_registered_users" and "-create_with_dotlrn_role ..." are common parameters and control the behavior.
- When the switch "-debug" is specified, the interface page (e.g. /oauth/github-login-handler) can be used for testing and to see the provided parameters ("claims") returned from the identity provider. In the testing mode, the user is not logged-in. Furthermore, on the public login pages of the OpenACS instance, the external entity is not offered.
- When the switch "-create_not_registered_users" is specified, the users authorized via the external identity provider not existing as users in OpenACS (based on the email address) are automatically created as new OpenACS users (automated account creation). By default, this switch is turned off.
- The parameter "-create_with_dotlrn_role ..." is useful for DotLRN instances. When it is defined, new users will be created as DotLRN users with the specified role (e.g. "student").
The configuration parameter can be provided when the login-handler objects are created, or these can be provided via the OpenACS configuration file. The parameters are looked up from the configuration file on a path based on the name of the login-handler object. So, with the following login-handler objects are defined
::ms::Authorize create ::ms::azure ::xo::oauth::GitHub create ::xo::oauth::github
the parameters for these objects can be specified during
creation (.... -client:id "..." ...) or in the
configuration file in the following sections:
ns/server/[ns_info server]/acs/oauth/ms/azure { ns_param tenant "..." ns_param client_id "..." ... } ns/server/[ns_info server]/acs/oauth/github { ... }
the parameters for these objects can be specified during creation (.... -client_id "..." ...) or in the configuration file in the following sections:
ns/server/[ns_info server]/acs/oauth/ms { ... }
Testing
For testing, it is recommended to define the login-handler objects with the optional "-debug" flag (see above). Add the login-handler object with the following command in xooauth/tcl/oauth-init.tcl file
xo::oauth::GitHub create ::xo::oauth::github \ -debug
This assumes that the GitHub as Identity Provider was defined on GitHub, and at least the parameters "client_id" and "client_secret" are defined in the OpenACS configuration file.
Then restart the server and navigate to YOURLOCATION/oauth/github-login-handler and you will see the option to login via GitHub. By clicking on the link, you will be redirected to GitHub for registering, and then you will be redirected to the interface page showing the claims provided by GitHub, and whether the user_id exists, etc.
When the login-handler objects are created without the "-debug" flag, the login options for all the created login-handler objects are listed on the register/login page of OpenACS (it is possible to omit these via a package parameter set on a subsite).
Example configuration with a custom login handler
Example for xooauth/tcl/oauth-init.tcl:
# # Potential place for creating login-handler objects for external # identity providers. # # xo::oauth::GitHub create ::xo::oauth::github \ # -client_id "..." \ # -client_secret "..." # # ms::Authorize create ms::azure \ # -tenant "..." \ # -client_id "..." # # # This is a custom login handler, # - configured to create unregistered users, # - using the "tenant" and "client_id" from the configuration file, and # - adding some site-specific actions after a successful registration # ms::Authorize create ms::LoginHandler -create_not_registered_users ms::LoginHandler object method register_new_user { {-first_names} {-last_name} {-email} } -returns integer { # perform first the "register_new_user" action as usual set user_id [next] # on successful registrations (no exception during "next") the user_id is returned. # Do whatever you want with this user_id, adding it to groups, etc. ns_log notice "ms::LoginHandler: new registration of user $email returned user_id $user_id" return $user_id }