Introduction
Web application that provides an SSO gateway to unify institutional and third-party SSO providers.
Discovery Endpoints
OAuth2 / OpenId Connect discovery (metadata) endpoints can be found at the following well-known paths.
-
-
URI(s): https://[tier: dev,pprd].gateway.login.vt.edu/.well-known/oauth-authorization-server
-
Exclude tier for production instance (e.g. 'https://gateway.login…')
-
-
-
-
URI(s): https://[tier: dev,pprd].gateway.login.vt.edu/.well-known/openid-configuration
-
Exclude tier for production instance (e.g. 'https://gateway.login…')
-
-
Setting up your App
Using the Gateway service is a multi-step process.
-
Create an Enterprise Directory group - or use an existing group - that will be the backing group for your developer team. Note: you must be an admin on the group used for your team. Each team member must be a member of the backing group. Select the desired tier based on needs (must use the same App Manager tier).
-
Create a Developer Team via App manager. Select the desired tier below based on needs.
-
Select Create Developer Team (if you don’t have one already)
-
Choose a group from the dropdown
-
-
Create an app under the newly created team
-
Click the Create App button on the App Manager homepage.
-
Choose a Developer Team from the dropdown.
-
Choose a name for your team.
-
Create App.
-
You should now be on the Dashboard for the new app.
-
The Client Id and Client Secret are the credentials used for communicating with the Gateway service.
-
Register a new O-Protocol Endpoint. This is the callback endpoint in your app/service that will handle auth/tokenn responses from Gateway. e.g. https://my.app.vt.edu/secure
-
-
App Manager Tiers
-
Authentication
The Gateway API requires different authentication methods depending on the endpoint being accessed.
Client Authentication
Endpoints secured by HTTP Basic authentication (i.e. client secret).
-
/oauth2/token — Token exchange
-
/oauth2/tinfo — Token info
-
/oauth2/revoke — Token revocation
Credentials may be specified by either of the following mechanisms:
-
HTTP Basic scheme
-
POST parameters
client_id
andclient_secret
per [RFC 6749, section 2.3.1](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1)
User Authentication
Endpoints security by HTTP Bearer authentication (Access Token).
-
/oidc/uinfo — User info
-
/oauth2/admin/tokens — Administrative token revocation
-
/oauth2/user/tokens — User-initiated token revocation
Gateway API
Authorize
GET /oauth2/authorize
OAuth2 AUTHORIZATION endpoint with support for PKCE. The parameters are those supported by the AWS Cognito AUTHORIZATION Endpoint as this endpoint proxies to the AWS endpoint.
Authorization
HTTP Auth is not required.
Query Parameters
Parameter | Optional | Description |
---|---|---|
|
|
OAuth2 |
|
|
OAuth2 |
|
|
OAuth2 |
|
|
OAuth2 |
|
|
OAuth2 |
|
|
OIDC |
|
|
OAuth2 PKCE |
|
|
OAuth2 PKCE |
|
|
Flag indicating that a user should be presented with the option to create a guest account. |
|
|
Flag indicating that a user is coming back from Onboard after successfully creating a new account. This is not intended to be set directly by a client and doing so will prevent a user from seeing the Gateway discovery page. |
Example Request
$ curl 'http://localhost:8080/oauth2/authorize?response_type=code&client_id=lota&redirect_uri=https%3A%2F%2Flota.example.com&state=LOTA874ABC&scope=profile+openid' -i -X GET
Example Response
HTTP/1.1 302 Found
Location: http://localhost:8080/?state=hhpF3O1f31MppqGr1hVoQs
Example Error Response
HTTP/1.1 302 Found
Location: https://client-inactive.example.com?error=unauthorized_client&error_description=Client%20is%20inactive
Token: Code Exchange
POST /oauth2/token
OAuth2 TOKEN endpoint for the code flow with support for PKCE. The parameters are those supported by the AWS Cognito TOKEN endpoint as this endpoint proxies to the AWS endpoint.
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
false |
OAuth2 |
|
false |
OAuth2 |
|
false |
OAuth2 |
|
true |
OAuth2 PKCE |
Example Request
$ curl 'http://localhost:8080/oauth2/token' -i -u 'jolene:j' -X POST \
-d 'grant_type=authorization_code&code=PR0X1ED&redirect_uri=https%3A%2F%2Fjolene.example.com'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 2317
{"token_type":"bearer","expires_in":3000,"scope":"openid email name","access_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJkNjViOWExNy1hYjUwLTQ4NDctYWM4Ny00YzM0Y2ZiY2Q2NGEiLCJhdWQiOiJqb2xlbmUiLCJzY29wZSI6WyJvcGVuaWQiLCJlbWFpbCIsIm5hbWUiXSwiaXNzIjoic29tZWJvZHkiLCJhY3RpdmUiOnRydWUsImV4cCI6MTczMzc4NDg5MiwiaWF0IjoxNzMzNzgxODkyLCJ0dGwiOjMwMDAsImp0aSI6IlVaQlQzTkxCWVNNWTQzTEhEMzRHVlNLSEZYVktHU0dBTiJ9.uKqKf1km_zNe9tCyJPXmPPaLE3huUpjsRzSGPpGacwW4WCSp7o2-h8yWRhKepwEu6fCPxjgPNQ3tSXUMreOMUxc83MJVy9IXhkC_VFvrJ5IcaYEReABJ9Drst0wREeJwVzQf8a_UK43OHcx6JJaM8T4NxgKGPcqYLbfMYPMolLP0LX5BehHmrflLaHSh5QVupNiR-PdpctoARn13iY4mQyguluSf5SBDfc2ODAnVy1hWr2-7B3U4dBa7bz9lzNrC81mgbiNbC9HJ4R1-yBkhoCYnp02Y7PvH7oKDsovBE2M8gVJqQb0_uIRkzqGnruNFFdTnWFvnjMwhnad1lV7u5g","refresh_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJkNjViOWExNy1hYjUwLTQ4NDctYWM4Ny00YzM0Y2ZiY2Q2NGEiLCJhdWQiOiJqb2xlbmUiLCJzY29wZSI6WyJvcGVuaWQiLCJlbWFpbCIsIm5hbWUiXSwiaXNzIjoic29tZWJvZHkiLCJhY3RpdmUiOnRydWUsImV4cCI6MTczMzc4Nzg5MiwiaWF0IjoxNzMzNzgxODkyLCJ0dGwiOjYwMDAsImp0aSI6IlNBRUNMWlRYV0w3S1IyREtESDgzOEtESFQ2Tk1YVEJaM0lJNFJHREhIVjQzSVZBRiJ9.hWOLN2jjI-xlbSRvIPVVjCe5ppeD5H2XuFNFhl8flHgZoxftNhe4Bi0oraHJ0f6hSI6dHvSY0j7FNYSjjnz2JEZYICJ3O5YRqCuWwiaL-zcDcW-b4qtlJVQ4JcaAuFB-swVIop7d6Vwn_6tErVVIQeAYFfu4G3ZJangxZUcYqmrW4rMtKuw1w38DMzKhYdF5rLvVWnBDyEd6r2ZyXuxoiGlyXLkNq0cqBAZHh5jNkBA_R9K94U-2yWf7HdJ_PaGr1aogsPOGiNk3JN0jNNCqt43ckl4aGHhwq4prlsRxk8nZLsUZcFZOhu7B6dzq_Pkm3dx0l66YGxCwyyQAP29ZpA","id_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJkNjViOWExNy1hYjUwLTQ4NDctYWM4Ny00YzM0Y2ZiY2Q2NGEiLCJpc3MiOiJzb21lYm9keSIsImFjdGl2ZSI6dHJ1ZSwidHRsIjozMDAwLCJub25jZSI6IkhES0QtOEg3JEhELUtESEE4TCIsImF1ZCI6ImpvbGVuZSIsInNjb3BlIjpbIm9wZW5pZCIsImVtYWlsIiwibmFtZSJdLCJuYW1lIjoiSm9sZW5lIEpvbGUiLCJleHAiOjE3MzM3ODQ4OTIsImlhdCI6MTczMzc4MTg5MiwianRpIjoiN0tSMlQyRUFYNlFCTFREODM4SERLRExEM0lWQUZTQUVDTFpUWFdMIiwiZW1haWwiOiJqb2xlbmVAdnQuZWR1In0.zyROhClrlgK7mbVwxWNjlGYXY6Iv8l9xTAS7p2xqBz2HkdrEOgoAAPiYywOjpOe8-_Scgd-UFCr4hWCtDkZwTHJ-pM38NCBiwVGub-om2_EDnIztTDWEMTFE3UkTyCfKisvchIZsE6OftaJJm0Xd53ckRcB2ucUVT7F7WkoKwcnuW2vCKMQ1OCDOdewllVP4_54WS65j-y_dXQyg4VY2QOcTECyHvY2_HxHfwMOm1HecXE1GzUgNQMRumggLer19kScjlCMo_TXJyvhCLsKpEJ6inknO8g3sfBi3YjanF1YOE3fjW_TnOlW0lKBPOLfxnjsqilcytbt6pAGor21_-A"}
Example Error Response
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 105
{
"error" : "unsupported_grant_type",
"error_description" : "Grant type must be authorization_code"
}
Token: Refresh Token Exchange
POST /oauth2/token
OAuth2 TOKEN endpoint for handling refresh token requests.
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
false |
OAuth2 |
|
false |
OAuth2 |
|
true |
OAuth2 |
Example Request
$ curl 'http://localhost:8080/oauth2/token' -i -u 'rho:r' -X POST \
-d 'grant_type=refresh_token&refresh_token=eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI5YzhhODRiZS0zMDg3LTQxZjItOTEwYy1mYzViODM5OGIwMzQiLCJhdWQiOiJyaG8iLCJzY29wZSI6WyJ0aGUtc2NvcGUiXSwiaXNzIjoic29tZWJvZHkiLCJhY3RpdmUiOnRydWUsImV4cCI6MTczMzc4Nzg5MiwiaWF0IjoxNzMzNzgxODkyLCJ0dGwiOjYwMDAsImp0aSI6IlZZTEpIT0FURVo2V1M0QjZRV1JVWERTN0dIUkpYNFdaUTdZSklVVlNKWloifQ.ngVkpilAMxkj0Iq3-frmFiegLRGPmSUQ1f_taSF9pZ6XbwkAr4ZX0Auqhw6xleJrbyShWJ50JrA07kaZ1dQXz76xuI3LMFW4_YqBlSzsauaLHd4GsA2nbYnTom6DoKkA9iPof22zhBlMuCco840jJijc8sTmNKaR-zR46mqRSMh6mlkrjKvI1yF68EAoGP2ZvBTF4nvq7VtJ5hJPR5BbzB3V7Nrrw3f0RF6ZpoaeknWdSEWRtlUjXSCDzguQnpxTm48jCoNsCneuRt0u8lTlhO24uZvlWDp2KyQPRjEaBlsn050ivowQb5A4Nq6ThNZHwkAoH7XnEFhB1qDtX7TlGg&scope=the-scope'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 1448
{"token_type":"bearer","expires_in":3000,"scope":"the-scope","access_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI5YzhhODRiZS0zMDg3LTQxZjItOTEwYy1mYzViODM5OGIwMzQiLCJhdWQiOiJyaG8iLCJzY29wZSI6WyJ0aGUtc2NvcGUiXSwiaXNzIjoic29tZWJvZHkiLCJhY3RpdmUiOnRydWUsImV4cCI6MTczMzc4NDg5MiwiaWF0IjoxNzMzNzgxODkyLCJ0dGwiOjMwMDAsImp0aSI6ImJiZDUwYmQ5LTEwMDYtNDliZi05ZDVhLTBlZTk0YWJlNTQwOSJ9.VXdp7m-aRxthgJnw5i4UUnFPizV-xy_HNP18Q6Lo1dwO9Ur0Jf0nRq0P1uD6uZxoLxnnWlHzVsMnAh2IyMQe9fNDKdbw9WfI98Mkn5zq6MRlRs5lkOvpxrrI1A9rhgfxSCdAy4wWjS1V9R_WqVNGJd9McVag19mNwS7ys0eOBanPRmg2f7o_BB7CgLLksd2_oHh3ZDvij8h47M0MvHxRnKvBws22ZYY5q04owUZwwdxo1DyC3QmdkaNs7PNXsH2-I5znfaWc6nZqgACYbRoSm4cA0ME-q08YV2CQiKPpAGcBFmlvnYqlBr7riSYD1DUrg-wkHx7r4jkzfVuDQZqQIQ","refresh_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI5YzhhODRiZS0zMDg3LTQxZjItOTEwYy1mYzViODM5OGIwMzQiLCJhdWQiOiJyaG8iLCJzY29wZSI6WyJ0aGUtc2NvcGUiXSwiaXNzIjoic29tZWJvZHkiLCJhY3RpdmUiOnRydWUsImV4cCI6MTczMzg0MTg5MiwiaWF0IjoxNzMzNzgxODkyLCJ0dGwiOjYwMDAwLCJqdGkiOiI3NmI0ZTc5My1jODFmLTRhYWItOTFhOS00NDAzOWYyMDU1MTkifQ.hdY9yk6yZrMd8AVspyWkV2snld-MzgWDCFpHisQSBVKgbUX8lYJTANbxAJKvtKUQbV8eDBAYdSX5EpZNhW7KzFBtGtmbZs4OM0Ox7qfeWVrJSNKAtykufC6lwEkdTo99hYrKwuPnf3OejpV2XxxF21nrqi1frADmgvlK-rxix8VbhoFrfaTleh0aiaDIZTs_1wSf5vTRjcALpp06ZAdNfhh4NgPljVJTU-5J9rpQyVC_H5RsQMGdpQ04Qnpq0DzDvrPD6Y04Nb1wejKISWOEGYZ4fyFbFgve7fTMqeYY3B0eBrATdcaiktwLhkvjc0TPa6Yimi5ZCuxKwrVK9Z3EnQ"}
Example Error Response
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 80
{
"error" : "invalid_grant",
"error_description" : "Invalid refresh token"
}
Token: Client Credentials Grant
POST /oauth2/token
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
false |
OAuth2 |
|
true |
OAuth2 |
Example Request
$ curl 'http://localhost:8080/oauth2/token' -i -u '12345678-90b0-1002-a0a1-ffbbbb923df0:s' -X POST \
-d 'grant_type=client_credentials&scope=c'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 804
{"token_type":"bearer","expires_in":3000,"scope":"c","access_token":"eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI0ZWIzNmY5Mi1mODlkLTQ0OGYtOThlMy1mNDYwZTdmYWRjNDUiLCJhdWQiOiIxMjM0NTY3OC05MGIwLTEwMDItYTBhMS1mZmJiYmI5MjNkZjAiLCJzY29wZSI6WyJjIl0sImlzcyI6InNvbWVib2R5IiwiYWN0aXZlIjp0cnVlLCJleHAiOjE3MzM3ODQ4OTEsImlhdCI6MTczMzc4MTg5MSwidHRsIjozMDAwLCJqdGkiOiJmNzcwMTYwMC01YTlkLTQ5NTQtODJkMi0yMjU2MmExNzg5ZDIiLCJ1c2VybmFtZSI6InNpZ21hIn0.Y_FDc2pC1XKH7aZpmxFlhnAAWgX5dPHtVcFpU_Uyuvkx9RR0yLW0b-y-VUooNBzc9Uw8U6jJLXHtOhjJU1PfE162r9rV8DhpmxHMpH8K41htXs787Db9scFdxTnYCLW8Sl1ZIPdS8xWepU8WMNEQ7zuNs27I84Lm5FgcMsVoehR0B9ePNsCUqKnBNgk7QZ683MmR9b23CE78I8z4PrJ_ohk7HTnhkBtKsvG1_3azNnuu7FO5EPyvwwtp1VdeRtHac9eELwD9m_da_2N9Ry7ClFCk6YNPnayhAPxiDLEBlh7R6Z5y3o06E0wdCn2hRI5ktKv8xnIbfEgQAqykoBbRrg"}
Example Error Response
HTTP/1.1 401 Unauthorized
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Basic
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 79
{
"error" : "invalid_client",
"error_description" : "Invalid credentials"
}
Revoke: Client-Initiated
POST /oauth2/revoke
OAuth2 token revocation endpoint.
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
false |
The token that the client wants to be revoked. |
|
true |
Token type hint. |
Example Request
$ curl 'http://localhost:8080/oauth2/revoke' -i -u 'client-id-a:clientAPassword' -X POST \
-d 'token=eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJjbGllbnQtaWQtYSIsImF1ZCI6ImNsaWVudC1pZC1hIiwic2NvcGUiOiJvcGVuaWQiLCJleHAiOjE3MzM3ODY4ODMsImlhdCI6MTczMzc4MTg4MywidHRsIjo1MDAwLCJqdGkiOiJ0b2tlbi10by1yZXZva2UtaWQifQ.kT3Pby8bMB8O0j-Y1qE1hrj9QY5e5AysZiQJua5Bf7FwPPhDnlIn_qK7KRohzjPvo3OSbcFEu7rLG_ZAX3ovmvhMHTrlcGdenyuDwyQHYvjoq92WYM9KrvFNVEt3JFPJyGqnNPghhzDArhaBuEW_ztZVa3V88Y7nDOs3TP8Xs-wIgC1oSd5IDtTkTopfFLJ6zxxeXk1T-0wu0MDt-Y4JllNkWyf0WFXAx9UWd5egAp335IWb5fwqbTTpBciLj0vW-yma8B3g7ELm4Nch8gJfSzaPxB7tTVhVYKU6SmNh66e8XERhPH8czlJK1zLqb8VdBFXvLCU_2qaGxvFH_IUupA'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: text/plain;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Example Error Response
HTTP/1.1 503 Service Unavailable
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 108
{
"error" : "operation_failed",
"error_description" : "Token still exists with ID: token-to-revoke-id"
}
Revoke: Client-Initiated Batch
POST /oauth2/client/tokens
OAuth2 revocation endpoint for revoking ALL tokens that were created for the authenticated client.
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Example Request
$ curl 'http://localhost:8080/oauth2/client/tokens' -i -u 'client-id-ra:clientRaPassword' -X POST
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: text/plain;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Example Error Response
HTTP/1.1 401 Unauthorized
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Basic
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 79
{
"error" : "invalid_client",
"error_description" : "Invalid credentials"
}
Revoke: User-Initiated
POST /oauth2/user/tokens
User-initiated OAuth2 revocation endpoint for removing all tokens belonging to the requesting user. If the optional
client_id
parameter is provided, all tokens issued to the user for the given client will be removed. Otherwise, all
tokens with a user uid
matching the user UID of the access token used for authentication will be removed.
Authorization
Bearer <access_token>. Pass the access token using the authorization header field.
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
true |
ID of a client used to narrow the user token revocation. |
Example Request
$ curl 'http://localhost:8080/oauth2/user/tokens' -i -X POST \
-H 'Authorization: Bearer eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJqZGpka2FES0ZrZCIsImF1ZCI6InNvbWUtY2xpZW50Iiwic2NvcGUiOiJvcGVuaWQiLCJleHAiOjE3MzM3ODY4ODMsImlhdCI6MTczMzc4MTg4MywidHRsIjo1MDAwLCJqdGkiOiJBTEtESERMS0RIS0Q5Njg3SkhLSCJ9.prgGJp5RtEzDl9LEFW0t4lNrxUXBKcBl6vACFeZuNHVaJ9826vsbyndONOQp0nKbYXjCjJ8ZgkcK3gXjrbNapyNoeVCKPNoSn1nleAxszXjcthNJS9CtRV4UWqenQtHT0GLobEAA5ikx4vX6N-kokwoaWBtEKkLGHwRYGr3VZkSL42pfKjnxBzAi8S2xH1-aB0mNVScz3prgC4AFQqwAQ84SOX9itJy516rQGuIR2kJyWho7uhDYrp7csf5GteheCdibJbONf__3EzMAdjFxzHon32ZiByquz7xBR1gKx9_58NBWcz9qmrQF5yeA0bJy2olbZq_am7kxqwsGBkBmPQ' \
-d 'client_id=some-client'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: text/plain;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Example Error Response
HTTP/1.1 503 Service Unavailable
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 102
{
"error" : "operation_failed",
"error_description" : "1 tokens remain after revocation attempt"
}
Revoke: Admin-Initiated
POST /oauth2/admin/tokens
Administrative token revocation endpoint with the following options:
-
Revoke ALL tokens issued by a specific client (client_id).
-
Revoke ALL tokens issued to a specific user (uid).
-
Revoke ALL tokens with a specific sub claim (sub).
-
Revoke ALL tokens issued to a user by a specific client (client_id, uid)
Note: At least 1 parameter is required.
Authorization
Bearer <access_token>. Pass the access token using the authorization header field.
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
true |
ID of a client to revoke tokens for. |
|
true |
Subject claim of the tokens to be revoked. |
|
true |
UID attribute of person whose tokens should be revoked. |
Example Request
$ curl 'http://localhost:8080/oauth2/admin/tokens' -i -X POST \
-H 'Authorization: Bearer eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsImF1ZCI6ImFkbWluLWNsaWVudCIsInNjb3BlIjpbIm9wZW5pZCIsImdhdGV3YXk6b2F1dGgyL3Rva2Vucy9hZG1pbiJdLCJleHAiOjE3MzM3ODY4ODMsImlhdCI6MTczMzc4MTg4MywidHRsIjo1MDAwLCJqdGkiOiJBRE1JTjFVU0VSIn0.q-UlOeXalT4XbpwD2lS5lXBKQ-1LA96uemkRqJhScg9evwmSIZPQXf_lVclDaetx15ejqEaCkGbubqDKibtoZL_l4laXB_pwgxNfdY7biiFAN8IrSE2hlH-CjHTllr4dw5ki15ybmvyP9P9_zMT4xr4ZRsegshAkPBsPhHVC4zHD7t_rdVikuCLj9YEtqws6F4Am5XQZ8jJfKvPpPpNpjnZtmlOv7Qus3mtSpDVXiXiS5hq0LmhLgwScV5gRRssG_J9Ut0VJSz_UlOze1Mg6frePWE7IiXjJQiQEZuHhLwBwauaF21UxmHuHO_8sCLJ0sG6838T23AO_CAuwwSLQaw' \
-d 'client_id=iss-client&uid=114839'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: text/plain;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Example Error Response
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
X-Frame-Options: DENY
Content-Length: 102
{
"error" : "invalid_request",
"error_description" : "sub or uid, and/or client_id is required."
}
Token Info
POST /oauth2/tinfo
OAuth2 token introspection endpoint.
Authorization
The client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization via HEADER. The secret is Basic Base64Encode(client_id:client_secret).
Form Parameters
Parameter | Optional | Description |
---|---|---|
|
false |
The token to look up. |
|
true |
Token type hint. |
Example Request
$ curl 'http://localhost:8080/oauth2/tinfo' -i -u 'client-id-token-info-pos:client_pw' -X POST \
-d 'token=eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiIxU09NRSNTVUJKRUNUMiIsImF1ZCI6ImNsaWVudC1pZC10b2tlbi1pbmZvLXBvcyIsInNjb3BlIjoib3BlbmlkIiwiZXhwIjoxNzMzNzg2ODkzLCJpYXQiOjE3MzM3ODE4OTMsInR0bCI6NTAwMCwianRpIjoidG9rZW4taWQtdG9rZW4taW5mby1wb3MifQ.K3WuwaCHYSpGuQZsWtJ-Vdvb3xSRXI77FFulgBsGAUxSYEpUKMKDzpDIlU86xeREibvNqAYnAMzGGP8Gwl53ravqDTeNXj-ACM_N0bRHAZapse-JP-rb2BwUMh5zSlvwa2MIpwsqGP55_irmu18eaxQVlfxKbvUDQdRXwNcMSEK33SpUj6_6ywBfrDxmVwpahGT8_67feUhbXQ9tfkVsXuDTUsyFvC0wgVz-9QOeHbSUQXYyrBmpn-O3fq7xdNF1WZmZAm1-HOKdhe_mgrYxZ0cAaNRRmo_-chiRTtFq-Lk4ugq9ydgvo9tnHcaLMqYtlukhD_nHiuW7hiqX0sPJrA'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Content-Length: 151
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
{"sub":"1SOME#SUBJECT2","aud":"client-id-token-info-pos","scope":"openid","exp":1733786893,"iat":1733781893,"ttl":5000,"jti":"token-id-token-info-pos"}
Sample Expired Token
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Content-Length: 22
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
{
"active" : false
}
User Info
GET /oidc/uinfo
OpenID Connect UserInfo endpoint The parameters are those supported by the AWS Cognito USERINFO endpoint as this endpoint simply proxies to the AWS endpoint.
Authorization
Bearer <access_token>. Pass the access token using the authorization header field.
Example Request
$ curl 'http://localhost:8080/oidc/uinfo' -i -X GET \
-H 'Authorization: Bearer eyJraWQiOiIyNzE4MzgyMTM0MDE2NzEyMzAwOTE4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJtY2t4QWlUZHNBa3hNZWciLCJhdWQiOiJzb21lYm9keSIsInNjb3BlIjpbIm9wZW5pZCIsImVtYWlsIiwibmFtZSIsImwiXSwiaXNzIjoic29tZWJvZHkiLCJpZF90b2tlbiI6IkNZVXRNa3NPbE9sTktDeGxmRE1sT2UyVCIsImFjdGl2ZSI6dHJ1ZSwiZXhwIjoxNzMzNzgxOTA2LCJpYXQiOjE3MzM3ODE4NzYsInR0bCI6MzAsImp0aSI6IkJPQkFDQ0VTU1RPS0VOMDk0NTdER0QifQ.5BIHTCSFYIGCzPFoWZ_G11YkytHZq5RtlhfY_RBQcmnM711mnPy149qriXX-OupTnRWLgBTHuerdJa3wtA5UpCKJjW2UHwykYUti0AtpS3jUpkrfYGtZYHiQzRZxISCAqHrbblJh_scTXr7r-sFc2dvDDylHu4GCZefSx-R3tXO0dNNR89AXo0BVavxbwTrbjbmdFuXSSk-IApZFlO_rzrCXAuBsM1_7LWIy-iiviXUIV0gZwBV2HfE4oK5asEK6dZRjdLtyKUAiuhiXMSDJWNzD3AV_9s4fz_JQiLRGzAmiP_PFYVBo0CIxMbEZdcbfiBulGessO5zkVahdW-QHsA'
Example Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 220
{"sub":"mckxAiTdsAkxMeg","aud":"somebody","scope":[],"iss":"somebody","name":"Bob Bobberann","active":true,"exp":1733781906,"l":"Bobsville","iat":1733781876,"ttl":30,"jti":"CYUtMksOlOlNKCxlfDMlOe2T","email":"bob@vt.edu"}
Example Error Response
HTTP/1.1 403 Forbidden
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token.", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Known Compatibility Issues
-
Spring Security < 5.2.0.RELEASE does not handle the JWK response correctly and will cause token exchange to fail. Use version 5.2.0 or greater, if at all possible. If that is not an option, you may have to write a custom NimbusAuthorizationCodeTokenResponseClient to handle the tokenResponse correctly.