Introduction
Welcome to the AssetWise Session service API!
Session service is used for the purpose of authentication within AssetWise common services. A user can have multiple session where each session consists of an authentication token and the context of user, which can be used to limit what a user sees. Session uses OIDC authentication to authenticate users when login to the service.
Quick links
- Jump to Swagger API documentation
Using the API
Users access the API by invoking an HTTP request method, most commonly GET or POST, to act on a resource. An HTTP request to the Session service can include parameters, while HTTP headers pass additional information to and from the server. However, a request will only return information through an authenticated session. If a client does not first authenticate against a server, the server response is 401: Unauthorized.
Acquire tokens
In this document we are going to address the questions related to the following topics:
- Session token.
- OIDC queries:
- How to register an IMS account.
- How to register an OIDC client secret.
- How to set up scopes/claims/permissions.
- How to generate a token from an OIDC client secret.
- How to generate a token from an IMS username and password.
- Session middleware.
Session token
Q: What are the different authentication methods and when one should be used over another? (Interactive IMS accounts vs OIDC client secrets and any others)
A: It depends on the kind of implementation that you want to have in your service.
Use one of the following methods:
If you want to add the session login UI, then use SessionUI NuGet package. Check authentication section for more details.
If you want to login but don’t want to consume the SessionUI package, use Session's
/Account/Login
endpoint. Check authentication section for more details.If you have client credentials with session scope and have generated an OIDC token, then use
/Session/Open
or/Session/Service/Open
endpoints. Check solution for how to use open endpoints for more details.If you have a username and a password, then again you can use one of the login mechanisms (No. 1 or 2) according to your needs.
If you have only a session token or an OIDC token, then you can use
/Session/Open
or/Session/Service/Open
endpoints. Check solution for how to use open endpoints for more details.If you have an OIDC token, but your endpoint needs a session token to authenticate, then use session middleware to get the desired result.
Q: How does one obtain a session token (using login/sign in button)?
A: The key thing to understand is that all the AssetWise services require a "session token". This token goes into the authentication header for all requests.
The question is then - how does one obtain a session token?
There are a few ways. But first it is important to understand that that we never
want the AssetWise service to know your credentials. Instead we depend on the
Identity Management Service (IMS) to securely deal with that. IMS in turn uses
OAuth (OIDC) flow to exchange your credentials for an "AccessToken" and the
AssetWise Session service then turns that into a SessionToken. When using the
browser, the Session service creates a _session
cookie for convenience.
You can think of a session token as something that encapsulates your IMS access token plus some additional information, e.g. the default context, settings, Power BI.
In some service's Swagger page that's using Session service (like DataStorage or Session), you can press the "Sign In" button. It will redirect you to Session service, which will (if needed) redirect you to IMS.
The easiest way to get going is to sign in via the web either using the service
which is using Session service (like DataStorage) or directly with Session
service. Then either use the Session service's Swagger UI to echo back the
session token, or send an HTTP GET request to
https://session.{your domain}.bentley.com/Session/Token
. This method works
because the _session
cookie is available for all services on that domain.
It will return something like this:
{
"value": "{SessionToken}",
"scope": "session",
"label": "session",
"expiresAt": "1606873564"
}
The value above represents the session token. Put it in the header of API requests as a "Bearer Token". Example using PowerShell:
# Login to Session service (at https://eus.aw-cs-eap.bentley.com)
# Once logged in, you can yet your session token from https://session.{your domain}.bentley.com/Session/Token?tokenLabel=session
$sessionToken = "{SessionToken}"
# Then use the session token in the header
$headers = @{
"Authorization" = "Bearer $sessionToken"
}
# Make a simple GET request
$result = Invoke-WebRequest -Uri "{your service URL}" -Method GET -Headers $headers
# And print it
$result.Content
Q: How and when to use the /Session/Open
or /Session/Service/Open
endpoints?
A: /Session/Service/Open
endpoint should be used when you have either an
unexpired OIDC token, or a session token, which will be expired in 5 minutes.
It is important to know that the .../Open
endpoints are used to open or create
a new session token. If a session token which is about to expire is provided,
the new session token with an expiry of 60 minutes will be created and returned
to the user along with the expiry time.
If you are using an OIDC token, add the token to the auth header and call
the https://session.{your domain}.bentley.com/Session/Service/Open?save=true
endpoint. It will return the session token along with the expiry:
{
"sessionToken": "{SessionToken}",
"expiresAt": "{ExpirationTime}"
}
OIDC
Q: How do I register an IMS account or how do I register an OIDC client secret?
A: IMS team handles this. Session service is not responsible for the creation of IMS accounts or OIDC client IDs and secrets.
Q: How do I set up scopes/claims/permissions?
A: If the scopes are for of creating client credentials, then contact the IMS team. Session is not responsible for creating a client.
But if your service needs some scopes to be added in the Session client so that it helps to access certain services, then contact Session service team for such an addition.
Q: How do I generate a session token from an OIDC client secret?
A: Firstly, if you have client credentials, then they should have a session
scope as one of its scopes. You can't directly use the
client credentials to obtain a session token, you first need to obtain the OIDC
token. After you have an OIDC token, then you can call
either /Session/Open
or /Session/Service/Open
endpoints to create a session.
Note: to get the required scopes for Session service and for different environments, please contact the Session service's team.
Q: How do I generate a token from an IMS username and password?
A: Use the login mechanism.
Session middleware
Q: When should Session middleware used?
A: Session middleware should be used when:
- You don't want to login to session.
- You already have an OIDC token with a session scope.
- You want to authenticate an endpoint using a session token, but also have an
OIDC token. It will:
- Validate the token given to you.
- Exchange a valid token with a session token.
Manage token lifetimes
This document will deal with questions related to tokens and their lifetimes and how to keep a session alive. This also addresses the questions related to session cookies.
Q: What is the validity of a session token or an IMS token?
A: Session tokens and IMS tokens are valid for 60 minutes.
Q: What is the validity of a refresh token?
A: 30 days.
Q: How to get the expiration date for my session token or access token?
A: You can use one of these methods:
- If you have the token, then it can be decoded to check the expiry (
exp
) value. - You can get both session and access token's expiry by using the
/Session/Token
endpoint and specifyingsession
as the label for Session tokens orBentleyAccess
for IMS access tokens. - If you are using one of the
.../Open
endpoints to get the session token, then you can find the expiry of the session token in the response.
Q: How to get the expiration date of a refresh token?
A: Use the /RefreshTokenStatus
endpoint.
# Set the header with either a session or an OIDC token
$headers = @{
"Authorization" = "Bearer $token"
}
# Call the /RefreshTokenStatus endpoint (no parameters are required)
$result = Invoke-WebRequest -Uri "https://session.{domain}/RefreshTokenStatus" -Method GET -Headers $headers
The result of this endpoint is either a true or a false value. True indicates a valid refresh token and false indicates that there are no active refresh tokens for that user.
Q: How to keep a session alive?
A: Choose one of these methods depending on your situation:
- If you want to use the session for long running background jobs, which run
for more than 60 minutes, use a refresh token provided by the Session
service. Session service does not automatically get a new access token using
the refresh token. When using it you won't need to login again to get a new
access token (IMS or session token), instead call
/Session/Token
to get a new access token from IMS and subsequently create a session token using the access token. Check the section for refresh tokens to get more details.
Note: access tokens acquired through refresh tokens also have a validity of 60 minutes. Their benefit is that you won't have to login again for the duration a refresh token is valid for (30 days) and use
/Session/Token
endpoint to get new access token.
- When you are not using a refresh token, then you'd need to get a new token
every 60 minutes, you need to consider the following:
- If you just need a session token to be renewed - use
the
/Session/Service/Open
endpoint when the token is about to expire. Check the acquire token section for more details on.../Open
endpoints. - If you want to renew the pair of tokens (IMS + session token), then login
again after expiration of token. Login operation can either be done using
the sign in button or the
/Account/Login
endpoint. Check authentication section for more details.
- If you just need a session token to be renewed - use
the
Q: How to get or set cookies in a session?
A: If you are using the SessionUI package, then cookies are set
automatically
by the Session service. But if you are using the /Account/Login
endpoint to
login, then you will need to set the cookies explicitly. Session uses the
following
endpoints to set and get cookies:
To set cookies: make a POST request to this URL:
https://session.{domain}.bentley.com/cookie/set
with two arguments: value and return URL.value
- indicates the value of the cookie. In Session service, the name of the cookie is_session
.returnUrl
- it's optional, indicates the value of return URL.
To get cookies: the
/GetCookie
endpoint is a method to retrieve the encrypted cookie, currently signed in on the Session service domain. The user must be already signed in for the endpoint to retrieve the cookie. The endpoint accepts one required argument -ReturnUrl
an optional callback path parameter. The return URL specifies where user will be redirected after cookie is set on the remote host. The callback parameter specifies where the form with cookie data is posted. If the callback parameter isn't set, it will be set to cookie controller set action and the form will be posted with cookie value and return URL.
Authentication
Authentication in Session service can be done in several ways listed below.
Using the /Account/Login
endpoint
Call this endpoint and provide the value of returnUrl
of your service. In the
following example, Session service is calling the /Account/Login
endpoint and
then redirects to Session's Swagger
page: https://session.{domain}/account/login?ReturnUrl=https://session.{domain}/swagger/index.html
.
After calling this endpoint, the user will be redirected to the login page from
IMS (environment specific) and after a successful authentication, the session
JWT is added to the HTTP context. We can use cookies to store the session JWT.
Using the Nuget package
Use the Bentley.Extensions.SessionUI
and Bentley.Extensions.BackplaneUI
packages to add a sign in button to your service.
Visit Session service's README
for more information.
If you click the sign in button, you will be redirected to the login page from IMS.
Using Session middleware
We can use the Session middleware to authenticate the user by using the
Bentley.Extensions.Session.Authentication
Nuget package. It allows for
authentication without using SessionUI.
Visit Session middleware docs
for more information.
If a user has an OIDC token, then a new session can be opened by using the
/Session/Service/Open
or /Session/Open
endpoints. To obtain an OIDC token
that can be passed to Session service using client credentials, the user should
create it with a Session scope. Contact the Session service's team to get the
value of the required scope.
# Login to Session service at https://session.{domain}
# Once logged in, you can yet your session token from
# https://session.{domain}/Session/Token?authority=https://qa-ims.bentley.com&label=session
$sessionToken = "{generatedSessionToken}"
# Then use the session token in the header
$headers = @{
"Authorization" = "Bearer $sessionToken"
}
# Call the Session service
$result = Invoke-WebRequest -Uri "https://session.{domain}/Session" -Method GET -Headers $headers
# Display the results
$result.Content
Authenticating client connections to the server requires three steps.
- Call the IMS Authority Service to obtain an IMS access token.
- Pass the IMS access token to the Session service to obtain a session bearer token.
- Parameterize the session bearer token into a Session service HTTP request header.
Session service expects a session token or an OIDC token to be included in all
API requests to the server in an authorization
header: Authorization: {sessionToken}
You must replace sessionToken
with the token obtained from the Session
service.
Refresh tokens
A refresh token is a token that can be used to acquire new access tokens. The lifetime of a refresh token is much longer compared to that of an access token. Refresh tokens can also expire, but are quite long-lived. When the current access token expires or becomes invalid, Session service provides the refresh token to IMS to obtain a new access token. The user needs to explicitly provide consent to acquire a refresh token in this manner.
To provide consent for the refresh token:
- Login to Session service.
- Click on the avatar icon on the top right corner.
- If the toggle for "Background tasks" is turned on, that means there already is a valid refresh token present. If it is turned off, click on it to turn it on. The amber color dot on the avatar icon indicates that no valid refresh token is present.
- After clicking the "Background tasks" option, a "Request for Approval" page will open. Click "Allow".
Pass the session token in the authorization header to the request.
"Authorization" = "Bearer {sessionToken}"
# To use a refresh token
$sessionToken = "{sessionToken}"
# Then set the SessionToken to Authorization header
$headers = @{
"Authorization" = "Bearer $sessionToken"
}
# Call the /Session/Token endpoint with forceRefresh set to true
$result = Invoke-WebRequest -Uri "https://session.{domain}/Session/Token?authority=https://qa-ims.bentley.com/&tokenLabel=BentleyAccess&forceRefresh=true" -Method GET -Headers $headers
# Display the results
$result.Content
Valid /Session/Token
endpoint query parameters:
Parameter | Description |
---|---|
authority |
Authority. Default is the IMS authority. E.g. on DEV - https://qa-ims.bentley.com/. |
label |
Scope of the requested token. Optional parameter. Default is - session (when both label and tokenLabel are left empty). |
tokenLabel |
Label of the requested token. Optional parameter. Default is - session (when both label and tokenLabel are left empty). |
forceRefresh |
Set to true to use the refresh token to get a new access token. Default is false. For continuous request with true value, it would return the same token if there is an existing token that's valid for >= 55 min. |
Either label
or tokenLabel
must be specified. We recommend to use tokenLabel
instead of label
. You can use both the parameters as well, but that is not
required.
Note:
label
is a unique name provided to each token stored for any account.BentleyAccess
is the default label for the IMS access token, which is created using Session service's IMS client (using Session service login).
PAT
A PAT (Personal access token) is used as a reference token to get any token from Session service. If you have a backend process that cannot prompt for credentials, for that flow we provide the personal access token functionality. The key notion here is that the user creates a “key” (which doesn't contain their credentials). This key can be exchanged later for other tokens (such as an access token, session token, etc).
Creating PATs
# To create a PAT
$sessionToken = "{generatedSessionToken}"
# Then set the session token to the authorization header
$headers = @{
"Authorization" = "Bearer $sessionToken"
}
# Call the CreatePAT endpoint
$result = Invoke-WebRequest -Uri "https://session.{domain}/CreatePAT?label=BentleyAccess&expiry=1" -Method PUT -Headers $headers
# Display the results
$result.Content
Here are the /CreatePAT
endpoint's available query parameters:
Parameter | Description |
---|---|
label | Label of the token, to associate it with the PAT (e.g. BentleyAccess ). For multiple tokens, enter comma seperated list of labels (e.g. BentleyAccess, session ). |
expiry | Validity of the PAT token, in number of days. |
Pass the session token in the authorization header to the request.
A successful request will return the PAT's value and ID.
{
"id": "29d31b17-ea94-c69e-efe9-eccd2ee4a778",
"pat": "{PAT}"
}
Save the response of the /CreatePAT
endpoint to use it later. There is no
other way to get the PAT and its value. If it is lost, you would need to create
a new PAT.
label
is a unique name provided to each token stored for any account.
BentleyAccess
is the default label for the IMS access token which is created
using Session service's IMS client (using Session service login).
To create a PAT for the session token, use the session
label. You can also
attach multiple tokens to the same PAT. To attach both session and the access
tokens to a single PAT, use comma seperated values for the label. E.g.
BentleyAccess, session
.
All the labels are case sensitive.
If you are creating a PAT for the session token, then PAT would be created for
the same context as the session token used in the authorization header to
request /CreatePAT
endpoint.
Using PATs
# To use an existing PAT
$PAT = "{PAT}"
# Then set the PAT as the authorization header
$headers = @{
"Authorization" = "Token $PAT"
}
# Call the /Session/Token/PAT endpoint
# patToken and cyclePat are optional parameters. patToken parameter is not
# required when we pass the PAT in the authorization header. cyclePat is by
# default set to true, which means the PAT will get invalidated after single use
# and a new PAT will be returned in the response for the next use.
$result = Invoke-WebRequest -Uri "https://session.{domain}/Session/Token/PAT?tokenLabel=BentleyAccess" -Method GET -Headers $headers
# Display the results
$result.Content
Here are the /Session/Token/PAT
endpoint's available query parameters:
Parameter | Description |
---|---|
patToken | A valid PAT. |
tokenLabel | Label of the requested token (e.g. BentleyAccess ). |
cyclePat | Set true if you want to cycle the PAT, else set false if you want to use the same PAT until it expires. Default value is true. |
To get an access token using a PAT, use BentleyAccess
as the token label. To
get a session token using a PAT, use session
as the token label.
There are two ways to make requests to this endpoint:
Pass the session token in the authorization header to the request. In this case, the patToken parameter is required:
"Authorization" = "Bearer {sessionToken}"
.Pass the PAT in the authorization header to the request. In this case the patToken parameter is not required:
"Authorization" = "Token {PAT}"
.
A successful request will return a JSON object:
Key | Description |
---|---|
access_token |
Requested token. |
expires_in |
Remaining time for the token expiry in seconds. |
auth_guid |
PAT to use for the next request. |
Get a session token from a BentleyAccess token
# Use the BentleyAccess token
$BentleyAccess = "{BentleyAccess_token}"
# Then set the BentleyAccess token to Authorization header
$headers = @{
"Authorization" = "Bearer $BentleyAccess"
}
# Call the /Session/Open endpoint
# Context is an optional parameters. If 'context' parameter is empty, then it
# will return the session token for the default context and if set to a valid
# context ID, then it will return session token for that specific context.
$result = Invoke-WebRequest -Uri "https://session.{domain}/Session/Open" -Method PUT -Headers $headers
# Display the results
$result.Content
Get a new session token from a BentleyAccess token
Call the /Session/Open?context={context_guid}
endpoint. The context
query
parameter must be a valid context ID. It is a optional parameter. If kept empty,
the default context will be used. Pass the session token in the authorization
header to the request. "Authorization" = "Bearer {BentleyAccess_token}"
A successful request will return a JSON object:
Key | Description |
---|---|
sessionToken |
Requested session token. |
expiresAt |
Expiry in the UNIX timestamp. |
Revoking PATs
To revoke an existing PAT, make a request to /RevokePAT?patId=<PAT_ID>
. Pass
a session token in the authorization header to the request:
"Authorization" = "Bearer {sessionToken}"
# To revoke a PAT
$sessionToken = "{sessionToken}"
# Then set the session token in the authorization header
$headers = @{
"Authorization" = "Bearer $sessionToken"
}
# Call the /RevokePAT endpoint
$result = Invoke-WebRequest -Uri "https://session.{domain}/RevokePAT?patId=f6fd1fa7-7e8..." -Method DELETE -Headers $headers
# Display the results
$result