Authentication
The Auth connector demonstrates the ability to configure authentication for individual services on a connector. Since i2 Analyze version 4.3.4, you can configure a connector service to require a user's credentials before initiating a query, be it synchronous or asynchronous. This mechanism enables connectors to authenticate users with third-party services.
Similar to client configurations, you can define reusable authentication configurations that can be shared across services in the connector configuration. These are groups of form fields that the user fills in with their credentials in order to authenticate.
After a user authenticates with a service using a specific authentication configuration, the user is able to query all services that use the same authentication configuration.
Note: Connector service authentication is completely separate from Liberty's user authentication. Connector service authentication is managed on the connector domain and controls access to connector services. Liberty's user authentication is managed by the i2 Analyze server, controlling access to the i2 Connect gateway.
Configuring authentication for a synchronous service
The following are the steps required to successfully set up authentication for a synchronous service.
1. Defining an authentication configuration
Authentication configurations are defined in the authConfigs
array of a connector's configuration. For example, the Auth connector defines two authentication configurations in its config.json
file:
{
"defaultValues": { ... },
"services": [ ... ],
"authConfigs": [
{
"id": "authConfig1",
"loginUrl": "/login/userpass",
"form": {
"description": "This service requires a username and password.",
"fields": [
{
"id": "username",
"label": "Username",
"type": "text"
},
{
"id": "password",
"label": "Password",
"type": "password"
}
]
}
},
{
"id": "authConfig2",
"loginUrl": "/login/apikey",
"form": {
"description": "This service requires an API key.",
"fields": [
{
"id": "apikey",
"label": "API Key",
"type": "password"
}
]
}
}
]
}
In the above, two authConfigs
are defined. Each configuration has:
- An
id
which needs to be unique among theauthConfigs
. - A
loginUrl
which is relative to the connector's base URL. This is used to determine where authentication requests should be made. - A
form
object which includes the following:- A
description
briefly describing the form. - A
fields
property which is an array of form fields. Each form field is an object containing:- An
id
unique among the form fields. - A
label
shown on the user interface alongside the form field. - A
type
indicating the type of user input. Accepted values aretext
andpassword
.
- An
- A
2. Assigning an authentication configuration to a service
For a general understanding about how to add a service, see Adding a service.
To configure a service to use an authentication configuration, add an authConfigId
field in the connector service definition and assign it the ID of the authentication configuration. For example:
{
"defaultValues": { ... },
"services": [
{
"id": "acquire-service",
"name": "Acquire Service",
"description": "Acquires all data. Requires authentication.",
"clientConfigType": "NONE",
"authConfigId": "authConfig1"
}
],
"authConfigs": [ ... ]
}
You cannot assign multiple authentication configurations to a single service. But you can assign the same authentication configuration to multiple services.
3. Implementing the login endpoint
The login endpoint is called when the user submits their credentials for a service using an authentication configuration.
Here, the submitted credentials should be checked to ensure they are valid. If they are, the login endpoint should generate an authorization token string and include that in the response body like so:
{
token: "authorization-token-string"
}
The Auth connector example generates signed JSON Web Tokens (JWTs) which the endpoint responds with as an example. You are free to use your own token generation and verification mechanisms.
This generated token is cached by the gateway and used in subsequent connector requests to services using the same authentication configuration.
If the credentials are invalid, the endpoint should respond with a 401
status code alongside an RFC7807 (ProblemDetails
) response body. This ProblemDetails
object contains the following fields:
- The
title
; a brief summary of the problem. - The
detail
; An explanation specific to the occurrence of the problem. The
type
; a URI reference that identifies the problem type. To indicate the problem is caused by a connector authentication error, this value must be set to:urn:uuid:264caa46-75cb-4ac5-891a-11adeb48b6fb
The
status
; the HTTP response code (usually a401
).- The
instance
; an optional URI reference which identifies the specific occurrence of the problem, relative to the connector's base URL. Absolute URLs are also accepted.
4. Implementing authentication verification on endpoints
The gateway uses bearer authentication to authorize requests made to protected resources. In this authentication scheme, security tokens are sent in the Authorization
header of the request, looking like the following:
Authorization: Bearer <token>
To implement verification of authentication for the service, the token submitted in the Authorization
header of the request needs to be validated.
If you are not outsourcing the verification of authentication tokens to a third-party service, your connector implementation will need to ensure the following:
- The
Authorization
header exists on the request - It starts with the
Bearer
prefix - The
<token>
exists and is valid (i.e. is the same as the one generated in the login request).
If the token is valid, the acquire endpoint should respond with entities and links as usual. If the above validation fails, the acquire endpoint should respond with a 401
and a ProblemDetails
body.
Additionally, if the connector service has a validate endpoint, the same restriction logic needs to be applied for it.
Configuring authentication for an asynchronous service
If you are not familiar with setting up and using asynchronous services on a connector, refer to the Async connector.
Similarly to configuring authentication for a synchronous service, an authentication configuration needs be defined and assigned to the asynchronous service you want to configure authentication for in the connector configuration.
To ensure requests to an asynchronous service are made by an authenticated user, all the query endpoints must validate the contents of the Authorization
header, similarly to how an acquire endpoint is configured for authentication. This includes the:
- Async acquire endpoint
- Status endpoint
- Results endpoint
This is because, even after launching the asynchronous query, it is possible for the token to expire or otherwise become invalidated while the query is running. In which case, the connector should respond with a 401
and ProblemDetails
body to the gateway to indicate that the user needs to reauthenticate before the query can continue. In such events, the client would request for the user to re-input credentials before the running query resumes or a completed query displays results.
The Delete endpoint can also validate the authentication token provided although this is not strictly necessary.
Setup
These instructions are for setting up and running the Auth connector.
If you are not familiar with deploying i2 Analyze with the i2 Connect gateway or deploying i2 Analyze with the Information Store and the i2 Connect gateway and have not previously done so, you must do so now.
1. Add connector to topology
In your topology.xml
file in toolkit\configuration\environment
, add a new <connector-id>
element for the Auth connector:
<wars>
<war ... name="opal-services-daod" ... >
...
<connector-ids>
<connector-id value="auth-connector"/>
</connector-ids>
...
</war>
</wars>
Additionally, add a new <connector>
element to the topology:
<ns1:topology ...>
...
<connectors>
<connector base-url="http://localhost:9086" name="Auth Connector" id="auth-connector"/>
</connectors>
</ns1:topology>
Ensure that you are using the same port specified in the auth\auth-connector\src\main\resources\application.properties
file in this repository (9086
by default), and that the value of the id
attribute is the same as the value
attribute of its corresponding <connector-id>
.
2. Configure the schema
Choose whether you want to configure the Auth schema as a connector schema or a gateway schema.
Connector schema
By default, your connector has the Auth schema configured as a connector schema. schemaUrl
, chartingSchemesUrl
, and schemaShortName
are defined in the Auth connector's config.json
file, in auth\auth-connector\src\main\resources
.
Additionally, ensure the following is true:
- The connector's
config.json
does not contain agatewaySchema
property. - The Auth
<connector>
element in your i2 Analyze topology does not contain agateway-schema
attribute.
For more information, see configuring a connector schema.
Gateway schema
If you want to set up the Auth schema as a gateway schema, follow the guidelines for configuring a gateway schema using the Auth schema and charting scheme in the schema
directory of this repository.
Additionally, ensure the following is true:
- The connector's
config.json
inauth\auth-connector\src\main\resources
does not contain theschemaUrl
,chartingSchemesUrl
andschemaShortName
properties. These properties exist on the configuration by default. If they are present, remove them. - The Auth
<connector>
element in your i2 Analyze topology does not contain aschema-short-name
attribute.
3. Run the Auth connector
To run the connector, navigate to connector\auth\auth-connector
in your terminal and run the application using the following command:
mvnw spring-boot:run
4. Deploy and start i2 Analyze
Deploy and start the Liberty server.
setup -t deployLiberty
setup -t startLiberty