Software Statement Assertion (SSA)#
Janssen Server provides SSA endpoint that enables management of SSAs. The SSA is a JSON Web Token (JWT) containing client metadata and some custom attributes. Specification for SSAs has been outlined as part of Dynamic Client Registration Protocol.
URL to access revocation endpoint on Janssen Server is listed in the response of Janssen Server's well-known configuration endpoint given below.
https://janssen.server.host/jans-auth/.well-known/openid-configuration
ssa_endpoint
claim in the response specifies the URL for revocation endpoint. By default, revocation endpoint
looks like below:
https://janssen.server.host/jans-auth/restv1/ssa
More information about request and response of the revocation endpoint can be found in the OpenAPI specification of jans-auth-server module.
Disabling The Endpoint Using Feature Flag#
/ssa
endpoint can be enabled or disable
using SSA feature flag.
Use Janssen Text-based UI(TUI)
or Janssen command-line interface to perform this task.
When using TUI, navigate via Auth Server
->Properties
->enabledFeatureFlags
to screen below. From here, enable or
disable SSA
flag as required.
Configuration Properties#
SSA endpoint can be further configured using Janssen Server configuration property ssaConfiguration
. When using
Janssen Text-based UI(TUI) to configure the properties,
navigate via Auth Server
->Properties
to update value for this property. This property take JSON configuration with
parameters as described below:
"ssaConfiguration": {
"ssaEndpoint": "{{your-url}}/ssa",
"ssaCustomAttributes": [
"myCustomAttr1",
"myCustomAttr2",
...
],
"ssaSigningAlg": "RS512",
"ssaExpirationInDays": 30
}
ssaEndpoint
— Base endpoint for SSA.ssaCustomAttributes
— List of custom attributes, which are received in the request when creating an SSA.ssaSigningAlg
— Algorithm to sign the JWT that is returned after creating an SSA.ssaExpirationInDays
— Expiration expressed in days, when an SSA is created and the expiration is not sent.
SSA Security#
To call SSA services, a token of type client_credentials
must be generated with the following scopes enabled:
https://jans.io/auth/ssa.admin
— Allows calling all SSA services.https://jans.io/auth/ssa.portal
— Allows only callGet SSA
service.https://jans.io/auth/ssa.developer
— Allows only callGet SSA
, but you can only filter ssa that have been created by the same client.
Create a new SSA#
Create SSA
for the organization with expiration
(optional).
Request body description#
Field | Detail | Optional |
---|---|---|
org_id | The "org_id" is used for organization identification. | false |
description | Describe SSA | false |
software_id | The "software_id" is used for software identification. | false |
software_roles | List of string values, fixed value ["password", "notify"] . |
false |
grant_types | Fixed value Fixed value ["client_credentials"] . |
false |
expiration | Expiration date. (Default value: calculated based on global SSA settings) |
true |
one_time_use | Defined whether the SSA will be used only once or can be used multiple times. (Default value: true) |
true |
rotate_ssa | TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA. (Default value: true) |
true |
lifetime | SSA Lifetime in seconds | true |
Note: You can add more custom attributes
in the request, (you must have previously configured in the SSA global
configuration).
It should be clarified that these values are persisted in the database and are not returned in the SSA JWT.
Example:
{
"org_id": "your-org-id",
"description": "your description",
...,
"myCustomAttr1": "Your value custom attr 1",
"myCustomAttr2": "Your value custom attr 2"
}
Response description#
Returned SSA is a JWT, containing the following structure:
{
"ssa": "eyJraWQiOiI1NTk3MGFkZS00M2MwLTQ4YWMtODEyZi0yZTY1MzhjMTEyN2Zfc2lnX3JzNTEyIiwidHlwIjoiand0IiwiYWxnIjoiUlM1MTIifQ.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoxLCJpc3MiOiJodHRwczovL2phbnMubG9jYWxob3N0Iiwic29mdHdhcmVfcm9sZXMiOlsicGFzc3d1cmQiXSwiZXhwIjoxNjY4NjA5MDA1LCJpYXQiOjE2Njg2NDE5NjcsImp0aSI6ImU4OWVjYTQxLTM0ODUtNDUxNi1hMTYyLWZiODYyNjJhYmFjMyJ9.jRgh8_aiwMTJxeT9cwfup9QP9LBc6gQstvabCzUOJvELnzosxiNJHeU2mrvavaNK6BGvs_lbNjODVDeetGCD48_F2ay9r8qmo-f3GPzdzcJozKgfzonSkAE5Ran9LKcQQJpVc1rDYcV2xYiJLJ6FSuvnoClkDEE1tXysxshLPs-GXOZE7rD8XUXzezuxZWUE1jXwA-EFajoat8CP6QulHGxlcn_sKIhawhGODxJPz4Pf3jgeZVLG_7HfRJgxNiKcdzQIxnkbdpuS-0Q4-oc5yntsXhFhn31Pa3vGsiPPH9f3ndL2ZZKk3xCgyImLDJuGaxXg-qEVoIG4zNWNHMUNUQ"
}
Header
alg
— The signature algorithm which usedRS256
.typ
— The type which used.kid
— The key identificationgluu-scan-api-rs256-ssa-signature-key
.
Payload
iat
— The time the JWT was created.iss
— The "iss" (issuer) claim identifies the principal that issued the JWT.jti
— The "jti" (JWT ID) claim provides a unique identifier for the JWT.software_id
— The "software_id" is used for software identification.org_id
— The "org_id" is used for organization identification.software_roles
— List of string values, fixed value["password", "notify"]
.grant_types
— Fixed value["client_credentials"]
.lifetime
— SSA lifetime in seconds.exp
— Expiration Time.myCustom1, myCustom2, ...
: if you have custom attributes, they will be displayed here.
Example:#
Request:
POST {{your-url}}/ssa
Content-Type: application/json
Authorization: Bearer {{your-token}}
{
"org_id": "your-org-id",
"description": "This is test description",
"software_id": "gluu-scan-api",
"software_roles": [
"passwurd"
],
"grant_types": [
"client_credentials"
],
"expiration": "1696799089",
"one_time_use": false,
"rotate_ssa": false,
"lifetime": 86400
}
Response:
HTTP/1.1 201 Created
Server: Apache/2.4.52 (Ubuntu)
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Content-Length: 757
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
{
"ssa": "eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg"
}
Get SSA#
Get existing active SSA based on jti
or org_id
.
Query Parameters#
jti
— Unique identifierorg_id
— Organization ID
Response description#
[
{
"ssa": {
"jti": "c3eb1c16-be9b-4e96-974e-aea5e3cf95b0",
"org_id": 1,
"software_id": "gluu-scan-api",
"software_roles": [
"password"
],
"grant_types": [
"client_credentials"
],
"iss": "https://jans.localhost",
"exp": 1668608852,
"iat": 1668608851,
"description: "test description",
"one_time_use": true,
"rotate_ssa": false,
"lifetime": 86400
},
"iss": "ed4d5f74-ce41-4180-aed4-54cffa974630",
"created_at": 1668608851,
"expiration": 1668608852,
"status": "ACTIVE"
}
]
- SSA
jti
— The "jti" (JWT ID) claim provides a unique identifier for the JWT.org_id
— The "org_id" is used for organization identification.software_id
— The "software_id" is used for software identification.software_roles
— List of string values, fixed value["password", "notify"]
.grant_types
— Fixed value["client_credentials"]
.iss
— The "iss" (issuer) claim identifies the principal that issued the JWT.exp
— Expiration time.iat
— Creation time.description
— Describe SSA.one_time_use
— Defined whether the SSA will be used only once or can be used multiple times.rotate_ssa
— TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA.lifetime
— SSA lifetime in seconds.myCustom1, myCustom2, ...
— if you have custom attributes, they will be displayed here.
iss
— The "iss" is related to the client that created this SSA.created_at
— Creation time.expiration
— Expiration time.status
— SSA status (ACTIVE
,USED
,EXPIRED
orREVOKED
).
Example:#
Request:
Get SSA using jti
.
GET {{your-url}}/ssa?jti={{your-jti}}
Content-Type: application/json
Authorization: Bearer {{your-token}}
Get SSA using org_id
.
GET {{your-url}}/ssa?org_id={{your-org_id}}
Content-Type: application/json
Authorization: Bearer {{your-token}}
Response:
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu)
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Content-Length: 432
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
[
{
"ssa": {
"software_id": "gluu-scan-api",
"grant_types": [
"client_credentials"
],
"org_id": 1,
"iss": "https://jans.localhost",
"software_roles": [
"passwurd"
],
"exp": 1668608852,
"iat": 1668608851,
"jti": "c3eb1c16-be9b-4e96-974e-aea5e3cf95b0",
"description: "test description",
"one_time_use": true,
"rotate_ssa": false
},
"iss": "ed4d5f74-ce41-4180-aed4-54cffa974630",
"created_at": 1668608851,
"expiration": 1668608852,
"status": "ACTIVE"
}
]
Get JWT SSA#
Get existing active SSA based on jti
.
Query Parameters#
jti
— Unique identifier
Response description#
Returned SSA is a JWT, containing the following structure:
{
"ssa": "eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg"
}
Header
alg
— The signature algorithm which usedRS256
.typ
— The type which used.kid
— The key identificationgluu-scan-api-rs256-ssa-signature-key
.
Payload
iat
— The time the JWT was created.iss
— The "iss" (issuer) claim identifies the principal that issued the JWT.jti
— The "jti" (JWT ID) claim provides a unique identifier for the JWT.software_id
— The "software_id" is used for software identification.org_id
— The "org_id" is used for organization identification.software_roles
— List of string values, fixed value["password", "notify"]
.grant_types
— Fixed value["client_credentials"]
.exp
— Expiration Time.myCustom1, myCustom2, ...
: if you have custom attributes, they will be displayed here.
Example:#
Request:
GET {{your-url}}/ssa/jwt?jti={{your-jti}}
Content-Type: application/json
Authorization: Bearer {{your-token}}
Response:
HTTP/1.1 201 Created
Server: Apache/2.4.52 (Ubuntu)
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Content-Length: 757
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
{
"ssa": "eyJraWQiOiJzc2FfNjY1MTQ5ODMtNzI0YS00OGQ2LWIzYzItODEyMGM1OTgyOGU2X3NpZ19yczI1NiIsInR5cCI6Imp3dCIsImFsZyI6IlJTMjU2In0.eyJzb2Z0d2FyZV9pZCI6ImdsdXUtc2Nhbi1hcGkiLCJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiXSwib3JnX2lkIjoieW91ci1vcmctaWQiLCJpc3MiOiJodHRwczovL2phbnMubG9jYWwuaW8iLCJsaWZldGltZSI6ODY0MDAsInNvZnR3YXJlX3JvbGVzIjpbInBhc3N3dXJkIl0sImV4cCI6MTY5Njc5OTA4OSwiaWF0IjoxNjk2NzEyNjg5LCJqdGkiOiJmNTRiYWFmZC02M2JmLTQ2NGEtYmJkZS00OTM3MDQ3NTBiMzUifQ.XTHzRrvrzQ5S_zEXjAWkXLegVIGK47zOa3eZuECO8xXQ2kOh0KXYGQ4TT3tPTFX19XQv30CLKqH97UPm-hkAMVL10NGUw_ernfoX1Z9-lTEdECPaqZ6UCiG1X8WRgJ0s4nUgE_PP9Isoyxnfk5bYlQwotf50KreTwDYUbwHRJZGdVPRjnLGeJpWhFblF4J5HNj_vU7wk7bdkaIDRArqK753mlCejXlkqTF97NzaL0bhP0yaoNK5jlscVPALQr2-FcoUl9rTfArSYXF1GuP3fhDN2BLrnB51M_8v7r0YkPF5B73ag82Aa8HSgYE6bmAB6D_M8W4v85idcyp0xQRPcIg"
}
Validate SSA#
Validate existing active SSA based on jti
Header Parameters#
- jti — Unique identifier
Response description#
Method returns status 200 with an empty body if the corresponding SSA exists and is active.
Example:#
POST {{your-url}}/ssa/validation
jti: {{your-jti}}
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu)
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
<Response body is empty>
Revoke SSA#
Revoke existing active SSA based on jti
or org_id
.
Query Parameters#
jti
— for revoke only one SSA, the specified by jtiorg_id
— for revoke all SSA of the specified organization.
Response description#
Method returns status 200 with an empty body if all required SSAs were revoked correctly.
Example:#
Request:
Revoke using jti
.
DELETE {{your-url}}/ssa?jti={{your-jti}}
Authorization: Bearer {{your-token}}
Revoke using org_id
.
DELETE {{your-url}}/ssa?org_id={{your-org_id}}
Authorization: Bearer {{your-token}}
Response:
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu)
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
<Response body is empty>
SSA Custom Script#
The custom script will allow us to modify the SSA process. SSA Custom Script
- Modify the JWT returned by the creation SSA web service.
- Modify the list returned by the get SSA web service.
- Run a process after revoking an SSA.
Create method#
This method is executed after having generated the jwt that the service will return.
In the following example, new fields is added to the header and payload of the JWT.
def create(self, jsonWebResponse, context):
print "Modify ssa response script. Modify idToken: %s" % jsonWebResponse
jsonWebResponse.getHeader().setClaim("custom_header_name", "custom_header_value")
jsonWebResponse.getClaims().setClaim("custom_claim_name", "custom_claim_value")
print "Modify ssa response script. After modify idToken: %s" % jsonWebResponse
return True
Parameters#
jsonWebResponse
— JWT with SSA structure usingio.jans.as.model.jwt.Jwt
classcontext
— Contains, SSA global configuration class, client, execution context, etc.
Get method#
This method is executed after having generated the SSA list that will be returned by the service.
def get(self, jsonArray, context):
print "Modify ssa response script. Modify get ssa list: %s" % jsonArray
return True
Parameters#
jsonArray
— Contains SSA list usingorg.json.JSONArray
classcontext
— Contains, SSA global configuration class, client, execution context, etc.
Revoke method#
This method is executed after the SSA list has been revoked.
def revoke(self, ssaList, context):
print "Modify ssa response script. Modify revoke ssaList: %s" % ssaList
return True
Parameters#
ssaList
— SSA revoked list.context
— Contains, SSA global configuration class, client, execution context, etc.
SSA Class structure#
The SSA entity contains the following fields:
id
typeString
— Unique class identifier, and is used as thejti
identifier for theJWT
.orgId
typeString
— Organization ID.description
typeString
— SSA Description.state
type enumSsaState
— Contains the following SSA status values (ACTIVE
,EXPIRED
,REVOKED
,USED
).creationDate
typeDate
— SSA Creation date.creatorId
typeString
— Client that created SSA.creatorType
type enumCreatorType
— Contains the following CreatorType values (NONE
,CLIENT
,USER
,AUTO
).ttl
typeInteger
— SSA lifetime in seconds.atributes
type classSsaAtributes
oneTimeUse
typeBoolean
— Whether the SSA will be single use.lifetime
typeInteger
— SSA lifetime in seconds.rotateSsa
typeBoolean
— TODO - Will be used to rotate expiration of the SSA, currently is only saved as part of the SSA.clientDn
typeString
— Client's DN.customAttributes
typeMap<String, String>
— Contain additional fields, previously configured in the SSA global configuration.softwareId
typeString
— Is used for software identification.softwareRoles
typeList<String>
— List of string values, fixed value["password", "notify"]
.grantTypes
typeList<String>
— Fixed value["client_credentials"]
.
Created: 2022-07-21