Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Naviga ID (formerly IMID) is Naviga's SSO (Single Sign-on) authentication and authorization service for all content creation tools. Built on the industry standard of JSON Web Token, Naviga ID integrates with organization's existing identity provider using OpenID Connect. OpenID Connect ensures compatibility with all major identity providers such as Google, Facebook, Azure AD and many more.
Naviga ID also supports the OAuth2 standard Client Credentials which is used to obtain access tokens for machine-to-machine communication scenarios, such as import and export of material to and from Naviga's content services.
Naviga ID has a role based authorization schema. Each role in Naviga ID corresponds to one or more permissions. Roles are set up by Naviga.
When a user logs into Naviga ID, the groups a user belongs to in the organization's identity provider are imported into Naviga ID.
Via Naviga ID's Admin service, organization administrators can configure the mappings between org groups and one or more service roles. Mappings can also include a unit, and will in that case limit the resolved permissions to only be applied to that unit. A unit can be viewed as a sub-organization within an organization. A mapping can also be created without including a unit, in that case the resulting permissions will be global for the organization, meaning they are valid in all units.
Every user belongs to an organization, for example "the media group".
The name of the organization is also part of your Dashboard domain name (for example https://mediagroup.dashboard.infomaker.io)
Use case Content Creation: Content access can be based, depending on your needs, to have everything open to the entire organization or be based on unites (see below). Some rights are also role based, such as publish flow possibilities (from Writer 6.0).
In some Dashboard applications, it is also possible to share specified content with the entire organization. This way it is possible to make concepts available to everyone, or only specific units. As a user creates or modifies content, that content is automatically labelled with the user organization.
A unit is defined by the publication that the user is part of, for example "South News" or "North News" within the organization.
Use case Content Creation: Content access is based on all the user units. For example in an application such as Dashboard Article Search, a user that belongs to two units will see articles from both these units (filtering using suggest search on channels or units possible with configuration).
Access control is unit wide which means that everyone within a unit can see the same content, and everyone with the right to edit content can edit all content within a unit.
A user can belong to one or many units, but only one unit can be "active" at the time. As a user creates content, that content is automatically "labelled" with the active unit. In our recommended setup, this will also make the content access right set to that unit. If a user modifies content, the object will contain this information but the access right will not be modified.
With some Dashboard applications it is also possible to share content with all or any of the units the user belongs to.
It is also good to know that all Dashboard configurations are made per unit (installed and available apps, specific app configuration, workspaces etc).
A group is defined by the working task that people are working with in the organization, for example reporters, editors etc. Groups are configured in the organization's identity provider.
Service Roles define the privileges for a specified service, for example what a Dashboard user can do. It could be power user, admin or read-only mode etc. Service Roles are global roles and defined by Naviga.
How roles are used is configured by your administrator: who can create, edit and delete concepts, who can create and edit lists, who can plan articles within the Publication Planner.
Use case Content Creation: In addition to defining privileges to specific functions, roles can also be used for setting workflow statuses (from Writer 6.0). This means that it is possible to allow internal journalists to publish without prior approval but contributors cannot publish directly for example. These workflow steps are fully customizable.
Service roles are not used for content access control.
Integration of an Identity Provider in Naviga ID using OpenID Connect requires some setup in the Identity Provider. Here you can find instructions for the most common providers and how to configure them to support Naviga ID.
The organisation "mediagroup"The unit "South News"The group "editor"The Service Role "dashboard:powerUser"This document describes how to integrate a custom Identity Provider using OpenID Connect with Naviga ID.
The party that wished to integrate with Naviga Login must have an identity provider compatible with the OpenID Connect 1.0 Core specification.
Specifically, the identity provider must support the OpenID Connect Authorization Code Flow.
Information we need to integrate your OIDC application:
URL to your (.well-known/openid-configuration)
Client ID
Client secret
The following URLs must be added to the integrating party’s Whitelisted Callback URLs or equivalent:
The following URLs must be added to the integrating party’s Allowed Web Origins or equivalent:
Moving to a new identity provider will, most of the time, involve a new subject ID for the user, resulting in a new subject ID in Naviga ID as well. To retain the users Naviga ID subject ID, the http://infomaker.io/originalSubject claim can be added to the organization token. This claim should consist of the subject ID the user had in the previous identity provider.
When encountering the http://infomaker.io/originalSubject claim, Naviga ID will replace the previous subject ID stored internally with the subject ID found in the sub
Param
Type
Description
publicData
Object
Required - Data to show in the error
internalData
Object
Required - Private data that can be logged in the error
Reply function to respond with the error
Overrides: ServiceAuthorizationError#hapiReply
Returns: Object - Response - Response object
Param
Type
Default
Description
replyOrResponseToolkit
Object
Required - Response toolkit - For example 'h' in Hapi, which handles the response
extraPublicData
Object
{}
Extra public data to shown in the error message
string
{
"name": "Service name (admin-api).",
"version": "Service version."
}{
"sub": "subject-id-from-current-idp"
"http://infomaker.io/originalSubject": "subject-id-from-previous-idp"
...
}ServiceAuthorizationErrorConfigError - extending the ServiceAuthorizationError error class
PublicMessage is set to 'Internal Server Error' and the HttpCode is set to '500'.
Thrown when building config variables while authorize.
Extends: ServiceAuthorizationError
ObjectReply function to respond with the error
Overrides: ServiceAuthorizationError#hapiReply
Returns: Object - Response - Response object
ServiceAuthorizationErrorAccessDenied Error - extending the ServiceAuthorizationError error class
PublicMessage is set to 'Access denied' and the HttpCode is set to '403'.
Thrown when a users credentials does not match the requested endpoints credentials.
Extends: ServiceAuthorizationError
ObjectReply function to respond with the error
Overrides: ServiceAuthorizationError#hapiReply
Returns: Object - Response - Response object
x-imid-req-id
A unique id for the request. Used for debugging purposes.
Yes
x-imid-token
Contains the IMID token if INCLUDE_IMID_TOKEN_IN_REQUEST is set to true.
Yes
x-forwarded-for
Used for identifying the originating IP address of the client. If included in the request, the original value will be prepended to the final header.
No
x-forwarded-port
Used for identifying the port that the client used to connect. If included in the request, the original value will be used.
No
x-forwarded-proto
Used for identifying the protocol (HTTP or HTTPS) that the client used to connect. If included in the request, the original value will be used.
No
x-forwarded-host
Used for identifying the original host requested by the client. If included in the request, the original value will be used.
No
Param
Type
Description
publicData
Object
Required - Data to show in the error
internalData
Object
Required - Private data that can be logged in the error
Param
Type
Default
Description
replyOrResponseToolkit
Object
Required - Response toolkit - For example 'h' in Hapi, which handles the response
extraPublicData
Object
{}
Extra public data to shown in the error message
Param
Type
Description
publicData
Object
Required - Data to show in the error
internalData
Object
Required - Private data that can be logged in the error
Param
Type
Default
Description
replyOrResponseToolkit
Object
Required - Response toolkit - For example 'h' in Hapi, which handles the response
extraPublicData
Object
{}
Extra public data to shown in the error message
Http server to help the systemtest visualize http calls.
Start the http server.
Listening on specified port.
Stop the Http server.
Checks if there are any http calls left to respond to or endpoints waiting for calls, responds to these endpoints and then stops the server.
Throws errror if there are leftover calls not handled before shutdown.
stringGets the server host.
Returns: string - networkInterfaceAddress - A string with the address for the eth0 network
Promise.<Object>Gets an endpoint to handle. Checks if an endpoint is waiting for an answer and resolves an answer to it.
Or puts the endpoint on a queue to be handled when a request for that endpoints comes in.
Returns: Promise.<Object> - Promise object represents the object with resolve, reject and params to resolve the incoming http call
Promise.<Object> | voidHandles all incoming Http calls
Either puts the request on queue to be handled or responds with data.
Returns: Promise.<Object> | void - Promise object represents an object with the data from the request or, returns void and puts the request in queue.
For services hosted behind an IMSG, nothing needs to be done. The IMSG does already support access tokens. The IMSG will take care of validating the access token and create a service token, just as if the API was accessed with an ID token.
Authentication means being sure of who the caller is
The steps required to ensure an access token is valid are the following:
Ensure ntt (Naviga Token Type) claim in the access token payload equals access_token
Read the kid (key id) from the access token header.
Fetch the corresponding public key from for stage env or for production env.
It's important that server clock is synchronized, if not, the application might accept tokens that have expired.
The keys published on /jwkscan, and should, be cached for up to 10 min in the application.
Note, a token with a kid that does not exist in a cached /jwks might still be a valid token. It might be that a new key has been published but not yet fetched by the application. For that reason, the application should re-fetch the /jwks (once) if an unknown kid appears.
Similarly, a key might be revoked at any time, so never cache /jwks for more than 10min. If /jwks is cached for a longer period of time, tokens with invalidated kid/signature can appear to be valid when they are not.
Authorization means knowing what actions the caller is allowed to do
Permissions are included as described by the payload below. Permission strings are on the format service_name:permission_name. Permissions in the permissions.org array should are valid in all units while permissions in permissions.units[unit_name] array is only valid in that specific unit.
More information about Naviga ID's permission model can be found on the page.
The Access Token payload is as follows:
This document describes how to integrate Microsoft Azure using OpenID Connect with Naviga ID.
When a new release of the Naviga ID access token service was deployed to production on Dec 20th, it broke backwards compatibility for the scope parameter in the fetch token endpoint when using client credentials. Previously the scope parameter had been ignored, but in the new version it was not. This caused clients that set the scope parameter to anything other than an empty string to fail to fetch tokens.
params
Object
Required - The params object containing properties passed to the constructor
params.port
number
Required - Port number to start the Http server on
params.enableHealthEndpointAt
string
Required - Url string with the endpoint to the healthcheck
endpoint
string
Required - Url string with the endpoint to either resolve or put on a queue
params
Object
{}
Object with params to the request. Example: treatContentTypeAs: 'application/json'
request
Object
Required - Request object with the incoming http call
response
Object
Required - Response object to respond to the incoming http call
Param
Type
Default
Description
args
Object
Required - The args object passed to the constructor
args.publicData
Object
Required - Data to show in the error
args.internalData
Object
Required - Private data that can be logged in the error
args.publicMessage
string
"An error occurred"
Error message to be shown
args.httpCode
number
500
Http status code for error
Param
Type
Default
Description
replyOrResponseToolkit
Object
Required - Response toolkit - For example 'h' in Hapi, which handles the response
extraPublicData
Object
{}
Extra public data to shown in the error message

imid_token
string
IM ID JWT
serviceCallback
string
Where to redirect client after login
"Redirected to the service callback url"GET https://[SERVICE URL].com/imsg-service/v1/health
Health status
{
"inGrace": false,
"stateChecksum": "A checksum string"
}{
"inGrace": false,
"stateChecksum": "No checksum string"
}GET https://[SERVICE URL].com/imsg-service/v1/login
Trigger login flow
callback*
string
Where to redirect client after login
org*
string
Which org to login with
GET https://[SERVICE URL].com/imsg-service/v1/token-is-set
Check if request contains IMID token
GET https://[SERVICE URL].com/imsg-service/v1/units
List all units a subject belongs to
GET https://[SERVICE URL].com/imsg-service/v1/org/{org}/login
Trigger login flow
callback*
string
Where to redirect client after login
POST https://[SERVICE URL].com/imsg-service/v1/logout
Log out
callback
string
Where to redirect client after logout
POST https://[SERVICE URL].com/imsg-service/v1/unit
Set preferred unit
unit
string
Preferred unit
Ensure alg (algorithm) in the access token header is identical to the key's alg
Use a suitable library for your language to validate the access-token signature using the key
Check that current time is less than exp in access token payload.
"Redirected after login"{
"msg": "ok"
}"errors.auth.MissingToken"{
"msg": "Unit set"
}"errors.auth.Forbidden""Redirected after login"{
"msg": "You are logged out"
}{
"msg": "Unit set"
}"errors.auth.Forbidden"{
"ntt": "access_token", // ntt stands for Naviga Token Type
"org": string, // org name
"sub": uuid_string, // subject is the unique user id in Naviga ID
"groups": [string, string,...], // groups the sub belongs to in the organization's identitity provider
"userinfo": {
"given_name": string, // optional
"family_name": string, // optional
"email": string, // optional
"picture": string // optional
},
"permissions": {
"org": [string, string,...] // permissions valid in all units,
"units": {
unit_string_name : [string, string...], // permissions only valid in unit unit_string_name
...
}
}
"iat": unix_timestamp_seconds, // issued at
"exp": unix_timestamp_seconds, // expires at
"jti": uuid_string, // token id
} Login to https://portal.azure.com/ and click on Azure Active Directory and the on App registrations (Preview)
Click on New registration
Name: <Your choice of name> Proposal: Naviga Login
Supported account types: Accounts in this organizational directory only (Standardkatalog)
Redirect URI (optional): Web /
Go to Authentication within your new created app and then following URLs under Redirect URIs as Web types (organization name will be provide to you by Infomaker/Newscycle):
https://imas.stage.imid.infomaker.io/v1/org/<OrganizationName>/login-callback
https://imas.imid.infomaker.io/v1/org/<OrganizationName>/login-callback
Go to API permissions and enable the following:
openid
offline_access
You can read more about user permissions and OpenId in the Azure documentation.
Go to Certificates & secrets and add a new Client secret
Description: client_secret
Expires: Your choice. But remember that you need to provide Naviga with a new Client Secret before the expiry date runs out otherwise your users will not be able to login with Naviga ID after the expiry date.
Copy the Value and keep it in a safe place. The value will be gone after you leave that page.
Go to Manifest and replace the following items:
This will include user groups in tokens
This will include given name and last name in tokens
You are now done with configuration
By default, Azure AD only provides group IDs in the token and in order for Naviga ID to fetch the names of those groups, additional configuration is required.
Under API permissions add the following delegated permission:
GroupMember.Read.All
This allows Naviga ID to list groups, read basic group properties and read membership of all groups the signed-in user has access to.
The infomartion needed by Naviga to complete the integration
Application (client) ID for you app
Example: 582fca63-a083-41f2-b8d2-0d35e3acf16f
Client secret for your app
The URL for OpenID Connect metadata document Example:
Create at least two accounts for Naviga. One for a regular user and one for a admin user (example [email protected] and [email protected]). This users should also be assigned to groups within Azure AD
options
Object
Required -
options.serviceTokenSignSecret
string
Required - Secret to validate token signature against
Extract and authorize token using the provided auth params
authParams
FullAuthorizationParameters | AuthorizationMode
Required - Authorization parameters to pass to
Error handler for errors thrown by ServiceAuthorizationMiddleware
Will handle telling IMSG to redirect unauthorized requests, but will pass on any other errors to next()
err
Object
Express err
req
Object
Required - Express req
res
Object
Required - Express res
The type definition of the full auhtorization object with all parameters.
Passed to the authorize function.
Properties
onPreAuth
function
Function to run before authorize is called
org
string | function | Boolean
Required - Organiztion to authorize against
accessRules
Array.<AccessRule>
Optional access rules to authorize against
The type definition of the access rule.
Passed to the authorize function within the object as a list of access rules.
All properties are optional, but at least one must exist
Properties
unit
string | function
Unit that should match token
permission
string | function
Permission that should match token
sub
string | function
Subject that should match token
Type defintion of the authorization mode.
SERVICE_ADMIN_ENDPOINT - Authorization validates if you are a service admin and have a valid token. Either accessed or thrown out.
OPEN_ENDPOINT - Authorization validates if you have a valid token and lets you through to the open endpoint. Either accessed or thrown out.
Either SERVICE_ADMIN_ENDPOINT or OPEN_ENDPOINT
The bug was present between 12:43 and 16:39 on December 20th 2021. During this time, only two applications belonging to the one customer are known to have experienced the issue. For the customer, this meant that one import flow and one export flow stopped working. The customer received workaround instructions at 15:24. Around one hour later, the problem was resolved when a fix was deployed to the access token service.
Naviga ID supports applications to authenticate themselves using client credentials. In return, an access token is sent that can be used to access Naviga's content creation services. One common use case is import and export applications.
The HTTP endpoint for fetching access tokens is designed to be compatible with the OAuth 2 standard. Apart from the credentials (client_id and client_secret), a parameter named scope is also defined the standard. Up until 12:43 on Dec 20th, the scope parameter had been allowed to be set, but its value had been ignored and carried no functionality. The reason for allowing scope to be set (even though not being in use) was to support tools and libraries that might default to set scope to an empty string unless otherwise configured.
Setting an empty scope variable was both supported and tested in Naviga ID. And, while it was also supported to set it to any string value, there were no test cases implemented for that scenario.
On Dec 20th, support for a new type of scope-based applications were added to Naviga ID. These new applications make use of the scope variable when fetching access tokens. Erroneously, the presence of a non empty string value in the scope parameter was used as an identifier for these new scope-based applications. When the system tried to handle a legacy application as a scope-based application, an internal error was triggered and a 500 HTTP error was returned. Because no test-case for this scenario existed for legacy applications, the problem was not identified during development.
Before the bug was fixed, one customer was identified that had two applications where the scope value was set to the string value "basic". A workaround for the customer was to remove the scope value. The fix in the access token service was to restore the previous behavior of ignoring the scope parameter for legacy applications.
December 10th, 12:02
-
Scope-based application support deployed to Naviga ID Stage. Backwards compatibility broken.
December 20th, 12:43
10 days
Scope-based application support deployed to Naviga ID Production. Backwards compatibility broken.
December 20th, 12:44
1min
Elevated 500 error levels but no alarm triggered
Stage environments are not used in similar enough fashion to prod environments. Had they been, this issue would have been found and fixed before reaching production systems.
In future feature development, implement stricter validation from the beginning. Fail fast and early. Catching all backwards compatibility scenarios gets a lot trickier when looser validation is implemented.
The impact of issues might seem greater than they are when triggered by one or two traffic intensive clients.
1. Login to your Google account and go to the API Manager
2. Click on Select a project dropdown and choose that project you want to use or create a new one.
3. Click on Create credentials and select the OAuth client ID
4. Google show a banner saying "To create an OAuth client ID, you must first set a product name on the consent screen". Click on Configure consent screen
5. Type the Product Name that will be shown to the users when they log in through GSuite, add infomaker.io as an Authorised domain and click Save.
6. Now we will fill in information about the app. Start with selecting Web application and provide a name for your app.
8. Under Restrictions, fill in following information:
Authorized JavaScript origins: https://imas.imid.infomaker.io, https://imas.stage.imid.infomaker.io
Authorized redirect URI: https://imas.stage.imid.infomaker.io/v1/org/<OrganizationName>/login-callback, https://imas.imid.infomaker.io/v1/org/<OrganizationName>/login-callback
9. Click on Create and your Client ID and Client Secret will now be displayed.
1. From the Admin console Home page, go to Security > API reference.
2. Check the Enable API access box.
3. Click save.
Search for Admin SDK
Click on Admin SDK and click on Enable
If you want Naviga Login to be able to fetch groups for the logged in user, a service account is required.
Create a service account and delegate domain-wide authority to it by following this guide: https://developers.google.com/admin-sdk/directory/v1/guides/delegation.
The following scopes are required to fetch user groups: https://www.googleapis.com/auth/admin.directory.group.readonly
Access to the G Suite Admin SDK requires impersonating a user with access to the Directory API:
Note: Only users with access to the Admin APIs can access the Admin SDK Directory API, therefore your service account needs to impersonate one of those users to access the Admin SDK Directory API. Additionally, the user must have logged in at least once and accepted the G Suite Terms of Service.
The information needed by Naviga to complete the integration
URL to your OpenID provider metadata file (.well-known/openid-configuration)
Client ID
Client secret
Private key file of the created service admin in JSON format
Email address or user ID of a user with access to the Directory API
Domain for which to retrieve the user groups
2022-09-09
Add scopes to filter access token permissions
permission-filter-include-org
permission-filter-include-unit:{unitName}
See for details.
2022-09-09
Upgrade internal dependencies
2022-06-28
Upgrade internal dependencies
2022-06-28
Upgrade internal dependencies
2022-06-22
Upgrade internal dependencies
2022-06-22
Upgrade internal dependencies
2022-06-16
Wildcard unit scope puts permissions into units if not allowed in org
Consider the following permissions:
Before this update, requesting a token with scope permission:*:writer:access would result in an error since writer:access is not present in the org permissions.
Now, requesting the same scope will result in the following permissions:
2022-04-28
Cache private keys to avoid exceeding SSM limit
2022-03-28
Default to less strict validation of cookie payload
Hapi, the web server framework used by IMSG, defaults to a strict validation of cookies according to rfc6265 (). This includes not allowing raw JSON as the cookie value. With this change, a less strict validation of cookies will be the default behaviour.
This will solve issues caused by other services setting cookies on or that do not adhere to rfc6265. The less strict validation is the default behaviour of most other servers as well as all major browsers.
Environment variable changes
This can be overridden by setting env variable STRICT_COOKIE_MODE to true.
2022-03-28
Internal maintenance
2022-03-28
For access tokens, use the permissions claim in the token instead of resolving permissions based on groups
There are two different kind of tokens in Naviga ID that can be used to access services behind an IMSG reverse proxy.
When you log in to CCT in the browser, an ID token (sometimes called session token) is stored as a cookie in your browser. This token does not hold any permissions. Instead, the groups that you belong to are stored in the token. When you access a CCT service, the IMSG will translate the groups into permissions (based on the current latest organization configuration). The permissions are then forwarded to the service.
The second type of token is access tokens. Access-tokens are fetched from the access token service using either an ID-token or client credentials. When an access token is created, it is populated with the resolved permissions from the start. Hence there’s no need for IMSG to try to resolve them again.
Up until this release, IMSG ignored any permission claim the access tokens and only used the list of groups to resolve the permissions. With this change in place, IMSG will always use the permissions claim in access tokens and forward those permissions to the service.
2021-05-07
Internal maintenance release. No changes to service.
2021-05-07
Upgrade of Node from 10 to 14.
Upgrade of dependencies
2021-03-01
Access tokens obtained through client credentials are now counted as internal access in the billing API
2021-02-04
Bugfix: validate IMSG service callback against correct cookie domain when using full URL in service callback
2021-01-29
Support for allowing any headers during CORS requests
IMSG can now allow any headers in CORS requests. Enabling this feature reflect the value of access-control-request-headers into the response access-control-allow-headers. Use with care.
Environment variable changes
CORS_ALLOW_ANY_HEADERS has been added.
Set to true to enable.
2021-01-20
Support for multiple domains
IMSG can now serve and set cookies on multiple domains. To enable multiple domains, set the IMID_COOKIE_DOMAINS environment variable to the domains you want to access IMSG on.
ex. IMID_COOKIE_DOMAINS="infomaker.io, navigacloud.com"
Environment variable changes
IMID_COOKIE_DOMAIN has changed name to IMID_COOKIE_DOMAINS and changed type from sting to CSV. The legacy name will continue to be supported.
2020-12-17
Legacy mode feature flag for units