If you are a NotifyBC administrator, you can manage following items in curated web console UI
-
-
Subscriptions
-
Notifications
-
Configurations
-
Administrators
-
Bounces
-
+
+ If you are a NotifyBC administrator, you can manage following items in
+ curated web console UI
+
+
Subscriptions
+
Notifications
+
Configurations
+
Administrators
+
Bounces
+
- Alternatively, use API Explorer to manipulate raw JSON object through REST API for maximum flexibility.
+ Alternatively, use
+ API Explorer to manipulate
+ raw JSON object through REST API for maximum flexibility.
+ For client_id in Authorize dialog, use {{ clientId }}.
+
-
-
+
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 5ef79e82f..a2ecbcc39 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -92,6 +92,7 @@ module.exports = {
'config/notificationBounce',
'config/workerProcessCount',
'config/middleware',
+ 'config/oidc',
],
},
{
diff --git a/docs/.vuepress/public/img/architecture.svg b/docs/.vuepress/public/img/architecture.svg
index 94796a2ae..36c2e2d74 100644
--- a/docs/.vuepress/public/img/architecture.svg
+++ b/docs/.vuepress/public/img/architecture.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/docs/api/administrator.md b/docs/docs/api/administrator.md
index 10745af4a..f98ff2e9f 100644
--- a/docs/docs/api/administrator.md
+++ b/docs/docs/api/administrator.md
@@ -4,7 +4,7 @@ permalink: /docs/api-administrator/
# Administrator
-The administrator API provides knowledge factor authentication to identify admin request by access token (aka API token), as opposed to possession factor admin ip list. Because knowledge factor authentication is vulnerable to brute-force attack, administrator API is less favorable than admin ip list. Administrator API is advised to be used only when obtaining client's ip or ip range is infeasible.
+The administrator API provides knowledge factor authentication to identify admin request by access token (aka API token in other literature), as opposed to possession factor admin ip list. Because knowledge factor authentication is vulnerable to brute-force attack, administrator API is less favorable than admin ip list. Administrator API is advised to be used only when obtaining client's ip or ip range is infeasible.
::: tip Example Use Case
Administrator API was created to circumvent an OpenShift limitation - the source ip of a request initiated from an OpenShift pod cannot be exclusively allocated to the pod's project, rather it has to be shared by all OpenShift projects. Therefore it's difficult to impose granular access control based on source ip.
diff --git a/docs/docs/config/oidc.md b/docs/docs/config/oidc.md
new file mode 100644
index 000000000..9f8529111
--- /dev/null
+++ b/docs/docs/config/oidc.md
@@ -0,0 +1,39 @@
+---
+permalink: /docs/config-oidc/
+---
+
+# OIDC
+
+_NotifyBC_ currently can only authenticate RSA signed OIDC access token if the token is a JWT. OIDC providers such as Keycloak meet the requirement.
+
+To enable OIDC authentication strategy, add _oidc_ configuration object to _/src/config.local.js_. The object supports following properties
+
+1. _discoveryUrl_ - [OIDC discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) url
+2. _clientId_ - OIDC client id
+3. _isAdmin_ - a predicate function to determine if authenticated user is _NotifyBC_ administrator. The function takes the decoded OIDC access token JWT payload as input user object and should return either a boolean or a promise of boolean, i.e. the function can be both sync or async.
+4. _isAuthorizedUser_ - an optional predicate function to determine if authenticated user is an authorized _NotifyBC_ user. If omitted, any authenticated user is authorized _NotifyBC_ user. This function has same signature as _isAdmin_
+
+A example of complete OIDC configuration looks like
+
+```js
+module.exports = {
+ ...
+ oidc: {
+ discoveryUrl:
+ 'https://op.example.com/auth/realms/foo/.well-known/openid-configuration',
+ clientId: 'NotifyBC',
+ isAdmin(user) {
+ const roles = user.resource_access.NotifyBC.roles;
+ if (!(roles instanceof Array) || roles.length === 0) return false;
+ return roles.indexOf('admin') > -1;
+ },
+ isAuthorizedUser(user) {
+ return user.realm_access.roles.indexOf('offline_access') > -1;
+ },
+ },
+};
+```
+
+In _NotifyBC_ web console and only in the web console, OIDC authentication takes precedence over built-in admin user, meaning if OIDC is configured, the login button goes to OIDC provider rather than the login form.
+
+There is no default OIDC configuration in _/src/config.ts_.
diff --git a/docs/docs/getting-started/overview.md b/docs/docs/getting-started/overview.md
index ae169e4d9..2a4ce42e6 100644
--- a/docs/docs/getting-started/overview.md
+++ b/docs/docs/getting-started/overview.md
@@ -69,18 +69,34 @@ A notification created by RSS feeds relies on dynamic token to supply the contex
## Architecture
+### Request Types
+
_NotifyBC_, designed to be a microservice, doesn't use full-blown ACL to secure API calls. Instead, it classifies incoming requests into admin and user types. Each type has two subtypes based on following criteria
- super-admin, if the source ip of the request is in the admin ip list and the request doesn't contain any of following case insensitive HTTP headers, with the first three being SiteMinder headers
+
- sm_universalid
- sm_user
- smgov_userdisplayname
- is_anonymous
-- admin, if the request is not super-admin but has valid access token that maps to an admin user created and logged in using the _administrator_ api, and the request doesn't contain any HTTP headers listed above
-- SiteMinder authenticated user, if the request
- - is neither super-admin nor admin, and
- - contains any of the 3 SiteMinder headers listed above, and
- - comes from either trusted SiteMinder proxy or admin ip list
+
+- admin, if the request is not super-admin and meets one of the following criteria
+
+ - has a valid access token associated with an builtin admin user created and logged in using the _administrator_ api, and the request doesn't contain any HTTP headers listed above
+ - has a valid OIDC access token containing customizable admin profile attributes
+
+ ::: tip access token disambiguation
+ Here the term _access token_ has been used to refer two different things
+
+ 1. the token associated with a builtin admin user
+ 2. the token generated by OIDC provider.
+
+ To reduce confusion, throughout the documentation the former is called _access token_ and the latter is called _OIDC access token_.
+ :::
+
+- authenticated user, if the request is neither super-admin nor admin, and meets one fo the following criteria
+ - contains any of the 3 SiteMinder headers listed above, and comes from either trusted SiteMinder proxy or admin ip list
+ - contains a valid OIDC access token
- anonymous user, if the request doesn't meet any of the above criteria
The only extra privileges that a super-admin has over admin are that super-admin can perform CRUD operations on _configuration_, _bounce_ and _administrator_ entities through REST API. In the remaining docs, when no further distinction is necessary, an admin request refers to both super-admin and admin request; a user request refers to both authenticated and anonymous request.
@@ -92,11 +108,31 @@ An admin request carries full authorization whereas user request has limited acc
- retrieve push notifications
- retrieve in-app notifications that is not targeted to the current user
-The result of an API call to the same end point may differ depending on the request type. For example, the call _GET /notifications_ without a filter will return all notifications to all users for an admin request, but only non-deleted, non-expired in-app notifications for authenticated user request, and forbidden for anonymous user request. Sometimes it is desirable for a request from admin ip list, which would normally be admin request, to be voluntarily downgraded to user request in order to take advantage of predefined filters such as the ones described above. This can be achieved by adding one of the HTTP headers listed above to the request. This is also why admin request is not determined by ip or access token alone.
+The result of an API call to the same end point may differ depending on the request type. For example, the call _GET /notifications_ without a filter will return all notifications to all users for an admin request, but only non-deleted, non-expired in-app notifications for authenticated user request, and forbidden for anonymous user request. Sometimes it is desirable for a request from admin ip list, which would normally be admin request, to be voluntarily downgraded to user request in order to take advantage of predefined filters such as the ones described above. This can be achieved by adding one of the HTTP headers listed above to the request. This is also why admin request is not determined by ip or token alone.
The way _NotifyBC_ interacts with other components is diagrammed below.
+### Authentication Strategies
+
+API requests to _NotifyBC_ can be either anonymous or authenticated. As alluded in [Request Types](#request-types) above, _NotifyBC_ supports following authentication strategies
+
+1. ip whitelisting
+2. Access token associated with an builtin admin user
+3. OpenID Connect (OIDC)
+4. CA SiteMinder
+
+Authentication is performed in above order. Once a request passed an authentication strategy, the rest strategies are skipped. A request that failed all authentication strategies is anonymous.
+
+The mapping between authentication strategy and request type is
+
+| | Super-admin | admin | authenticated | anonymous |
+| --------------- | ----------- | ----- | ------------- | --------- |
+| ip whitelisting | ✔ | | | |
+| Access token | | ✔ | | |
+| OIDC | | ✔ | ✔ | |
+| SiteMinder | | | ✔ | |
+
## Application Framework
_NotifyBC_ is created on Node.js [LoopBack](https://loopback.io/). Contributors to source code of _NotifyBC_ should be familiar with LoopBack. [LoopBack Docs](https://loopback.io/doc/en/lb4) serves a good complement to this documentation.
diff --git a/docs/docs/getting-started/usage.md b/docs/docs/getting-started/usage.md
index d21be02e0..af258988b 100644
--- a/docs/docs/getting-started/usage.md
+++ b/docs/docs/getting-started/usage.md
@@ -27,9 +27,15 @@ Anonymous authentication status is indicated by the LOGINlogin button.
+If you are an authorized _NotifyBC_ administrator and it's not always feasible to access _NotifyBC_ from a client in admin ip list, you can authenticate using an access token or, if configured, OIDC.
-The access token in API Explorer is integrated with web console. Therefore if you change access token in API Explorer GUI, it will be reflected in web console upon page refresh, and vice versa.
+The procedure to obtain and apply access token is documented in [Administrator API](../api/administrator.md). Access token authentication status is indicated by the _Access Token_ text field on top right corner of web console. You can edit the text field. If the new access token you entered is invalid, you are essentially logging yourself out. In such case _Access Token_ text field is replaced by the LOGINlogin button.
+
+If you have configured [OIDC](../config/oidc.md), the login button will direct you to OIDC provider's login page. Once login successfully, you will be redirected back to _NoitfyBC_ admin console.
+
+::: warning Tokens are not shared between API Explorer and admin console
+Despite API Explorer appears to be part of admin console, it is a separate application. At this point the login tokens are not shared between the two applications. You have to use API Explorer's _Authorize_ button to authenticate even if you have logged into admin console.
+:::
## SiteMinder authenticated user
diff --git a/docs/docs/getting-started/what's-new.md b/docs/docs/getting-started/what's-new.md
index 647ef866a..1a1350889 100644
--- a/docs/docs/getting-started/what's-new.md
+++ b/docs/docs/getting-started/what's-new.md
@@ -8,6 +8,11 @@ permalink: /docs/what's-new/
_NotifyBC_ has been built on Node.js [LoopBack](https://loopback.io/) framework since 2017. LoopBack v4, which was released in 2019, is backward incompatible. To keep software stack up-to-date, unless rewriting from scratch, it is necessary to port _NotifyBC_ to LoopBack v4. Great care has been taken to minimize migration effort.
:::
+## v2.3.0
+
+- Issue [#15](https://github.com/bcgov/NotifyBC/issues/15): Support OIDC authentication for both admin and non-admin user
+- misc web console adjustments
+
## v2.2.0
- Issue [#14](https://github.com/bcgov/NotifyBC/issues/14): Support Administrator login, changing password, obtain access token in web console
diff --git a/docs/index.md b/docs/index.md
index 94c56f4bf..b1c2eff59 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -8,7 +8,8 @@ features:
- title: Versatile
details: >
-
Anonymous or CA SiteMinder authenticated subscriptions