OAuth 2.0 integration for developers
Refer to the information below for more detailed information about integrating with OAuth 2.0.
Configurable system properties
There are a number of system properties that we provide:
Name | Key | Default value | Notes |
---|---|---|---|
Default refresh token duration |
| 30 | Number of days to set for the refresh token expiry if the OAuth 2.0 provider does not supply one. |
Minimum required access token lifetime |
| 30 | Minimum required lifetime of the access token if the refresh token is not available. |
Max clock skew |
| 60 | Maximum acceptable clock skew between client and an authorization server, in seconds. This property is also used as a maximum clock skew between nodes in product cluster. |
Max client delay |
| 60 | Maximum acceptable delay of responses from the client, in seconds. |
Max server delay |
| 60120 | Maximum acceptable delay of responses from an OAuth server, in seconds. |
Minimum lifetime of invalid tokens |
| 30 | The minimum days lifetime of an invalid token before removing it from the database. |
Prune expired tokens schedule |
| 0 0 23 * * ? | The cron expression for the scheduled token pruning job. Default is 23:00 everyday |
Default monitor stripe count |
| 64 | Default number of stripes which will be used for concurrent operations throughout the framework such as token refreshes. |
Skip baseurl https requirement |
| false | Can be used to skip the requirement that the Jira instance baseurl is https (not recommended) |
Skip provider https requirement |
| false | Can be used to skip the requirement that OAuth 2.0 providers endpoints use https (not recommended) |
Unrecoverable token failing period days |
| 7 | Minimum period after which still failing token should be considered unrecoverable |
These properties are set on the jira-config.properties
file
Custom values for JIRA's remaining advanced configuration options (i.e. not stored in the JIRA database) are stored as individual key-value pairs in a file called jira-config.properties
(located in the JIRA application home directory). Typically, these options are of little interest to most JIRA system administrators. While these key-value pairs can be edited, JIRA must be restarted for any changed values to take effect.
jira.projectkey.warning = testwarning
jira.projectkey.description = testdescription
...
atlassian.oauth2.client.unrecoverable.token.failing.period.days = 7
In new JIRA installations, this file may not initially exist and if so, needs to be created manually. For more information about editing the
jira-config.properties
file, see Edit the jira-config.properties file in the Jira server.
Using the configuration as a Plugin Developer
We provide REST API only to do CRUD related with client configurations. It’s available on {{baseurl}}/rest/oauth2-client/latest/config/ URL
.
You don’t need to use most of these endpoints, unless you plan to implement your own UI.
Specific requests:
GET
request will return list of all configurations.POST
request with client configuration as a body (see below) will store new configurations.{ "name": "Test client", "description": "Mail handler", "type": "GENERIC", "clientId": "someclientid", "clientSecret": "secretP4ssw0rd", "authorizationEndpoint":"https://authorizationserver.com/oauth2/authorize", "tokenEndpoint": "https://authorizationserver.com/oauth2/token", "scopes": [ "offline_access", "Mail.Read" ], "redirectUriSuffix": "WuBLhHpPAguypjRS7906Jg" }
GET
request to the{{baseurl}}/rest/oauth2-client/latest/config/{{id}}
will return configuration of a client with a specified id.DELETE
request to the{{baseurl}}/rest/oauth2-client/latest/config/{{id}}
will remove configuration of a client with a specified id.PUT
request to the{{baseurl}}/rest/oauth2-client/latest/config/{{id}}
will update configuration of a client with a specified id. The configuration should be send in body (for the format, see the abovePOST
request).GET
request to the{{baseurl}}/rest/oauth2-client/latest/config/get-redirect-uri?authorizationEndpoint={authEndpoint}
will return a unique redirect URI generated for a given authorization endpoint as a query parameter.
You can explore our API using the attached postman collection:
Plugin interfaces
There are many of interfaces provided that are useful for connecting to third parties with OAuth 2.0.
These can be imported with Spring Scanner.
ClientConfigStorageService
final ClientConfigurationEntity savedEntity = clientConfigStorageService.save(ClientConfigurationEntity.builder()
.name(---) // (Required)
.providerType(ProviderType.GENERIC) // or ProviderType.MICROSOFT, or ProviderType.GOOGLE (Required)
.description(---) // (Optional)
.clientId(---) // (Required)
.clientSecret(---) // (Required)
.authorizationEndpoint(---) // (Required)
.tokenEndpoint(---) // (Required)
.scopes(---) // (Required)
.build()
);
final ClientConfigurationEntity fetchedEntityById = clientConfigStorageService.getByIdOrFail(savedEntity.getId());
final ClientConfigurationEntity fetchedEntityByName = clientConfigStorageService.getByName(savedEntity.getName());
final List<ClientConfigurationEntity> fetchedEntities = clientConfigStorageService.list();
clientConfigStorageService.delete(savedEntity.getId());
FlowRequestService
final ClientConfigurationEntity clientConfiguration = clientConfigStorageService.getByIdOrFail(id); // id of a saved configuration
final FlowRequest flowRequest = flowRequestService.create(
session, // HttpSession of current request
clientConfiguration,
id -> pluginPage + "/" + id // pluginPage here will describe a landing page after completing the FlowRequest
);
... Complete flow on UI
final FlowResult flowResult = flowRequestService.getFlowRequest(
session, // HttpSession from same user as above
flowRequest.getId()
);
if (flowResult.indicatesSuccess()) { // true if the FlowRequest was successful
final ClientTokenEntity clientToken = clientTokenStorageService.save(
ClientTokenEntity.builder(flowResult.toSuccessResult())
.configId(clientConfiguration.getId()) // config id used above
.build()
);
} else {
final FlowResultError flowResultError = flowResult.toErrorResult();
// Handle FlowResultError...
}
ClientTokenStorageService
final ClientTokenEntity clientToken = clientTokenStorageService.getByIdOrFail(id); // using saved client token id from FlowResult
clientTokenStorageService.save(ClientTokenEntity.builder(clientToken)
.configId(---) // (Required)
.accessToken(---) // (Required)
.accessTokenExpiration(---) // (Required)
.refreshToken(---) // (Required)
.refreshTokenExpiration(---) // (Required)
.build()
);
clientTokenStorageService.delete(clientToken.getId());
TokenHandler
// This will automatically refresh and save the client token if required
final T result = tokenHandler.execute(
clientTokenId, // id of saved client token
clientToken -> // ... execute code that uses token. Can return T.
);
// This will automatically refresh, save, and return the most up to date client token
final ClientToken refreshedToken = tokenHandler.getRefreshedToken(clientTokenId);
TokenService
final ClientTokenEntity clientToken = clientTokenStorageService.getByIdOrFail(clientTokenId);
final ClientConfigurationEntity clientConfiguration = clientConfigStorageService.findByIdOrFail(clientToken.getConfigId());
// Will refresh and return the token. Note this will not save it.
final ClientToken forceRefreshClientToken = tokenService.forceRefresh(clientConfiguration, clientToken);
// Will refresh if the expiry + margin is after the current system time. Note this will not save if refreshed.
final ClientToken marginRefreshClientToken = tokenService.refreshIfNeeded(clientConfiguration, clientToken, Duration.ofDays(1));