Skip to content

Commit

Permalink
updated docs
Browse files Browse the repository at this point in the history
  • Loading branch information
f-w committed Feb 16, 2021
1 parent c3dcf5d commit d6f8e57
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 25 deletions.
38 changes: 25 additions & 13 deletions client/src/components/home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,36 @@
<template>
<div>
<h2>Welcome</h2>
<p>If you are a NotifyBC administrator, you can manage following items in curated web console UI
<ul>
<li><router-link to="/subscriptions">Subscriptions</router-link></li>
<li><router-link to="/notifications">Notifications</router-link></li>
<li><router-link to="/configurations">Configurations</router-link></li>
<li><router-link to="/administrators">Administrators</router-link></li>
<li><router-link to="/bounces">Bounces</router-link></li>
</ul>
<p>
If you are a NotifyBC administrator, you can manage following items in
curated web console UI
</p>
<ul>
<li><router-link to="/subscriptions">Subscriptions</router-link></li>
<li><router-link to="/notifications">Notifications</router-link></li>
<li><router-link to="/configurations">Configurations</router-link></li>
<li><router-link to="/administrators">Administrators</router-link></li>
<li><router-link to="/bounces">Bounces</router-link></li>
</ul>
<p>
Alternatively, use <router-link to="/api-explorer">API Explorer</router-link> to manipulate raw JSON object through REST API for maximum flexibility.</p>
Alternatively, use
<router-link to="/api-explorer">API Explorer</router-link> to manipulate
raw JSON object through REST API for maximum flexibility.
<span v-if="clientId"
>For client_id in Authorize dialog, use {{ clientId }}.</span
>
</p>
</div>
</template>

<script>
export default {}
export default {
data: function() {
return {
clientId: window.oidcClientId,
};
},
};
</script>

<style scoped>
</style>

<style scoped></style>
1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module.exports = {
'config/notificationBounce',
'config/workerProcessCount',
'config/middleware',
'config/oidc',
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/.vuepress/public/img/architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/docs/api/administrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
39 changes: 39 additions & 0 deletions docs/docs/config/oidc.md
Original file line number Diff line number Diff line change
@@ -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_.
48 changes: 42 additions & 6 deletions docs/docs/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
<img :src="$withBase('/img/architecture.svg')" alt="architecture diagram">

### 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.
10 changes: 8 additions & 2 deletions docs/docs/getting-started/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ Anonymous authentication status is indicated by the LOGIN<span class="material-i

## Admin user

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. 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 LOGIN<span class="material-icons">login</span> 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 LOGIN<span class="material-icons">login</span> 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

Expand Down
5 changes: 5 additions & 0 deletions docs/docs/getting-started/what's-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ features:
- title: Versatile
details: >
<ul>
<li>Anonymous or CA SiteMinder authenticated subscriptions</li>
<li>Anonymous or authenticated subscriptions</li>
<li>Multiple authentication strategies</li>
<li>Push and in-app pull notifications</li>
<li>Email and SMS push notification channels</li>
<li>Unicast and broadcast message types</li>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "notify-bc",
"version": "2.2.0",
"version": "2.3.0",
"dbSchemaVersion": "0.8.0",
"description": "A versatile notification API server",
"keywords": [
Expand Down

0 comments on commit d6f8e57

Please sign in to comment.