- Pre-installation step: Declaring the SSO Configurations
- Deploy on production environment
- Generate the update site yourself (from sources)
- Generate the oauth2.nsf database yourself (from source)
- Using the Rest API
- Ask the local domino Server to load plugin code from the workspace
The goal of this project is to transform a standard IBM Domino v9.0.1 server into an OAUTH2 authorization server (also know as an OAUTH2 provider), with OpenID extensions. Your server will generate access tokens that client applications will be able to use to access protected resources. Resource servers will be able to validate the token using a standard token introspection endpoint.
Please, note that nor the client applications, nor the protected resources have to be hosted on a Domino Server !
I didn't want to take the risk of storing keys myself. Instead, I prefered using SSO Configurations which are natively stored by IBM in a secure manner.
So, when Domino will generate OAUTH2 access tokens, it will use secrets stored in SSO configuration documents.
You will have to generate three of them :
- One key that will be used to sign the access token.
- Another one to sign the OpenID token.
- And a last one to encrypt the refresh token.
To create the three needed SSO Configurations, open your names.nsf, go to the "Servers" view, and use the "Web/Create Web SSO Configuration" action :
- Name your configuration: For example "AccessToken", "IdToken", and "RefreshToken"
- Enter the name of your organisation: We will use "ACME" in this example.
- DNS Domain: ".acme.com". This information is mandatory, but will not be used.
- Domino Server Names: Enter the name of the servers that will act as OAUTH2 authorization servers.
The dom-spring plugins must be deployed into your Domino Server. Documentation on how to deploy the plugins is available in the README file of the project on git hub :
https://github.com/lhervier/dom-spring
The procedure is almost the same as for the dom-spring plugins.
First, download the latest update site from the github release page, and unzip it where you want.
Then, create a new database named "Oauth2UpdateSite.nsf" (you can name it the way you want) on your server, using the "Eclipse Update Site" advanced template.
Open the database with your Notes client, and click on the "Import local update site" button. Go select the "site.xml" in the unzipped version of the update site.
Add (or update) the notes.ini variable "OSGI_HTTP_DYNAMIC_BUNDLES". It must point to your "Oauth2UpdateSite.nsf" database. Use a comma to separate multiple values if you already have another entry (for dom-spring for example).
Restart the http task (console command):
restart task http
Check that plugins are deployed :
tell http osgi ss oauth
You should see something like this :
> tell http osgi ss oauth
[1C04:0002-1C08] 28/09/2017 14:27:39 Framework is launched.
[1C04:0002-1C08] 28/09/2017 14:27:39 id State Bundle
[1C04:0002-1C08] 28/09/2017 14:27:39 95 <<LAZY>> com.github.lhervier.domino.oauth.server_1.0.0.qualifier
[1C04:0002-1C08] 28/09/2017 14:27:39 96 RESOLVED com.github.lhervier.domino.oauth.external.commons_io_2.5.0
[1C04:0002-1C08] 28/09/2017 14:27:39 99 RESOLVED com.github.lhervier.domino.oauth.external.nimbus_jose_jwt_4.37.1
This database will store the definition of the authorized OAUTH2 client applications. It will also store the authorization codes. Because of this, it is a sensible database, and you will have to be strict with its ACL.
You can download the "oauth2.nsf" database from the release page of github. Just copy it to your Domino server, and don't forget to sign it. Note that beacuse it contains a XPage, it must be signed with an id allowed to run unrestricted agents.
Users with the [AppManager] role will be allowed to register/edit/remove oauth2 client applications. Users with this role MUST also be able to add users in the Domino Directory (we will generate users on the fly)
Users with the [AuthCodeManager] role will be able to access all the generated authorization code documents. These are sensible data, protected with a reader field. Nobody should have this role. It is present for development purpose, and can be replaced by the "Full access Administrator" option of Domino Administrator.
Every other users that should be able to log into one of the OAUTH2 client application should have reader access.
So, by default, the ACL is :
- Anonymous "no access"
- "LocalDomainAdmins" as manager with [AppManager] and [AuthCodemanager] roles.
- Default "reader" to allow every regular Domino users to log in via OAuth2.
This project uses the Domino Spring project. As such, it is using properties that are readed by the Spring Framework. The code doesn't care about where they come from. And Spring is able to access properties from about anywhere.
To make our database work, we will have to declare a set of properties. But we can declare them in multiple places :
- From environment variables
- From notes.ini variables
- Or we can inject them ourself by writing a simple osgi plugin that extends the domino spring plugin (and store those properties in an external database for example).
I will show you how to declare them with any of those methods. But first, let's describe the properties and their awaited values :
Property | Description | Example value |
---|---|---|
oauth2.server.db | Path to the oauth2 database. Needed to prevent the endpoint to be made available on ALL databases of the server. | oauth2.nsf |
oauth2.server.nab | Path to a std Domino Directory in which we will generate the users associated with the registered client apps. | names.nsf |
oauth2.server.applicationRoot | When we will create a user for an application, we will name it using the application name and this prefix. | /O=APPLICATION |
oauth2.server.refreshTokenConfig | Name of the SSO configuration that contains the secret we will use to encrypt the refresh tokens. | ACME:RefreshToken |
oauth2.server.refreshTokenLifetime | Lifetime in seconds of the generated refresh tokens. Should be a long value (10h). | 36000 |
oauth2.server.authCodeLifetime | Max time ellapsed (in seconds) between user login and the server asking for the access token. | 60 |
oauth2.server.core.signKey | Name of the SSO configuration that contains the secret we will use to sign the access tokens. | ACME:AccessToken |
oauth2.server.core.iss | Issuer of the access token (iss property of the JWT). | https://acme.com/domino/oauth2/ |
oauth2.server.core.expiresIn | Lifetime in seconds of the generated access tokens. | 1800 |
oauth2.server.openid.signKey | Name of the SSO configuration that contains the secret we will use to sign the openid id tokens. | ACME:IdToken |
oauth2.server.openid.iss | Issuer of the openid id token (iss property of the JWT). | https://acme.com/domino/oauth2/openid/ |
oauth2.server.openid.expiresIn | Lifetime in seconds of the generated id tokens. | 36000 |
Whatever the method you use to define those properties, when done, restart the http task.
Eveything is in the title. Just edit your notes.ini file, and add variables named the same way as the properties.
You can also declare the variables in a configuration document.
Read the documentation of the Domino Spring project, or contact me (create an issue) if you want more details.
This method allows you to inject values from the place you want. And of course, most of my clients wants to extract parameters from a common NSF.
Use your browser to access the following url :
http://<your server>/oauth2.nsf
You will have to login with a user with the [AppManager] role.
Registering an application will add a user in the nab. The application secret is its http password. Don't forget to save this value. We won't be able to extract it again.
Authorize endpoint : http://server/oauth2.nsf/oauth2-server/authorize
Token endpoint : http://server/oauth2.nsf/oauth2-server/token
RFC7662 Access Token Introspection End point : http://server/oauth2.nsf/oauth2-server/checkToken
OpenID UserInfo end point : http://server/oauth2-server/userInfo (note that there is NO reference to oauth2.nsf !!!)
Authorization Code, Implicit and OpenID Hybrid flows are supported.
Client Credentials, and User credentials flows are NOT supported.
All OpenID scopes are supported : openid, profile, email, address, etc...
First, clone or download the source code from github into a local folder.
Refer to the dom-spring project page to donwload it.
- Go to File/Preferences menu, in the "Domino Designer" section, and check "Enable Eclipse plug-in install"
- Now, go to File/Application/Install menu.
- Select "Search for new features"
- Add a "Zip/jar location" and go find the zip that correspond to the dom-spring update site.
- Click Finish, and accept licences.
- Designer will ask to restart.
- Open Domino Designer
- Open the "package explorer" view, right click in the blank part, and select Import.
- In the "General" section, select "Existing projets into workspace"
- Click "Browse" and select the folder named "domino-osgi" in this project's sources.
- Select all projects and click "Import"
The code is now imported in your IBM Domino Designer. It should compile fine.
Open the file named site.xml in the "domino-osgi/com.github.lhervier.domino.oauth.update" project, and click the "Build all" button.
Download the XPages SDK zip file from :
https://www.openntf.org/main.nsf/project.xsp?r=project/XPages%20SDK%20for%20Eclipse%20RCP
Unzip the file to the folder of your choice. Then, in Eclipse, go to the menu "Help / Install new software".
In the dialog box, click the "add" button in from of the "Work with" combo :
- Name = XPages sdk
- Click the "Folder" button, and go find the folder named "org.openntf.xsp.sdk.updatesite" in the extracted zip file.
Select all features, accept licences, "Install anyway" when prompted to, and restart Eclipse.
Open Eclipse preferences, and go to the section "XPages SDK" :
- Enable using IBM DOMINO on this computer
- Enter the path to the notes.ini, the installation folder of your Domino Server, and the path to your data folder.
- Click "Automatically create JRE for domino"
- And "Apply".
This will create a new JRE Runtime, and a new Target platform. Select them :
- Go to the section "Java / Installed JREs", and select the newly created JRE (XPages Domino JRE)
- Go to the section "Plugins Development / Target platform", and select the newly created target platform (Domino Target).
- Menu Help / Install New Software
- Add an update site
- Go find the update site (the zip file) you juste downloaded
- Click next, finish, etc... until Eclipse ask to reboot.
In the package explorer, right click :
- Select "Import", then choose "General / Existing project into workspace".
- Go search for the folder where you cloned the sources
- And import the projects.
The code should compile fine.
Once the code is deployed, you will be able to generate the update site by opening the site.xml file of the "com.github.lhervier.domino.oauth.update" project. Simply click the "Build all" button.
As the dom-spring plugins are not available at maven central, you must first install them manually. For this, follow the README.md file present in the dom-spring github website :
- Install "IBM Domino Update Site for Build Management", let's say in c:\UpdateSite
- Download dom-spring source code
- In the source folder run the maven install command : mvn install -Dnotes-platform=file:///c:/UpdateSite
Now that your local maven repository is initialized, generate the oauth2-dom-auth-server update site. CD into the "domino-osgi" folder, and just type :
mvn install -Dnotes-platform=file:///c:/UpdateSite
The update site will be generated in
/domino-osgi/com.github.lhervier.domino.oauth.update/target/com.github.lhervier.domino.oauth.server.update-<version>.zip
Instead of copying it from github, in Domino Designer (you cannot use Eclipse here !), import the project named "oauth2-ondisk".
Then, create a new NSF on the server using the standard Domino Designer tool (right click/Team Development/etc...)
A rest API is provided. For the moment, it does not work with a bearer token :) You will have to send the username and the password of an authorized user (ie, a user with the [AppsManager] role, in the "Authorization Basic" header :
Authorization: Basic <username:password encoded in base 64>
You will then have the following APIs :
GET /api/applications :
Sample return value :
[
{name:"app1", clientId:"azerty"},
{name:"app2", clientId:"qsdfgh"}
]
GET /api/applications/<client id>
Sample return value :
{
"name": "app1",
"clientId: "azerty",
"redirectUri": "http://acme.com",
"redirectUris": ["http://acme.com/login", "http://acme.com/init"]
"readers": "*"
}
POST /api/applications
{
"name": "app1",
"redirectUri": "http://acme.com",
"redirectUris": ["http://acme.com/login", "http://acme.com/init"]
"readers": "*"
}
Sample return value :
{
"clientId": "azerty",
"secret": "a generated super secret password"
}
POST /api/applications/<client id>/put
{
"redirectUri": "http://acme.com",
"redirectUris": ["http://acme.com/login", "http://acme.com/init"]
"readers": "*"
}
You cannot change nor the name, nor the client id with this API. Note that we are not using a PUT request because the Domino Servers don't allow such requests by default (and I don't want to add a mandatory configuration update)
GET /api/applications/<client id>/delete
Again, the API is using a GET request instead of a DELETE request because DELETE request are forbidden at the server level by default.
If you want to play with the code, you will have to make your local Domino Server aware of the plugins compiled by your IDE.
If you already have imported the dom-spring plugins, you should have already installed the IBM Domino Debug Plugin in Eclipse or Domino Designer, and declared a debug configuration.
Simply go editing this debug configuration, and select the new plugins that corresponds to oauth2-dom-auth-server.
Click run, and when done, restart the http task.
Check that plugins are deployed :
tell http osgi ss oauth2
You should see something like this :
> tell http osgi ss oauth
[1C04:0002-1C08] 28/09/2017 14:27:39 Framework is launched.
[1C04:0002-1C08] 28/09/2017 14:27:39 id State Bundle
[1C04:0002-1C08] 28/09/2017 14:27:39 95 <<LAZY>> com.github.lhervier.domino.oauth.server_1.0.0.qualifier
[1C04:0002-1C08] 28/09/2017 14:27:39 96 RESOLVED com.github.lhervier.domino.oauth.external.commons_io_2.5.0
[1C04:0002-1C08] 28/09/2017 14:27:39 99 RESOLVED com.github.lhervier.domino.oauth.external.nimbus_jose_jwt_4.37.1