Skip to content

Commit 8c5abbf

Browse files
authored
Merge pull request #5 from jgomer2001/agama-lab-branch
General enhancements to project
2 parents 41afeca + 1f81a30 commit 8c5abbf

24 files changed

+1093
-667
lines changed

README.md

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,80 @@
22

33
Use this project to delegate authentication to an external OpenID Connect provider (OP) using the *authorization code flow*.
44

5-
## How it works at a glance
5+
## Anatomy
66

7-
When the main flow of this project is launched (namely, `io.jans.inbound.openid`) the user's browser is redirected to the authorization page of the configured OP. There authentication takes place and subsequently an access token is obtained to grab user profile data. A user entry is inserted in the local Jans database and a session is created for such "local" user in the Jans Authorization Server. Finally the user's browser is taken to the registered redirect URI.
7+
The project consists of three flows that provide incremental functionality:
88

9-
## Requirements
9+
- `org.gluu.inbound.oauth2.AuthzCode`: With this flow the user's browser is redirected to the authorization page of an external OP (the specifics are passed in the input parameters). Authentication takes place there and subsequently an access token is obtained and returned to the caller of the flow
1010

11-
### Enabled Agama
11+
- `org.gluu.inbound.oauth2.AuthzCodeWithUserInfo`: This flow launches `AuthzCode` and then obtains the profile data of the authenticated user by presenting an access token. Both the token and profile data are returned to the caller
1212

13-
Ensure Agama is [enabled](https://docs.jans.io/head/admin/developer/agama/engine-bridge-config/#availability) in your Jans Server.
13+
- `org.gluu.inbound.openid`: This flow launches `AuthzCodeWithUserInfo` and inserts an entry in the local Jans database for the user in question. Depending on how the flow is parameterized, this flow can perform a preliminar OpenID client registration
1414

15-
### External OP settings
15+
## `openid` flow
1616

17-
Obtain the following from the OP you want to support:
17+
Most of times, this is the flow that developers will want to reuse in their projects. It receives two input parameters:
1818

19-
- The authorization endpoint URL
20-
- The token endpoint URL
21-
- The userinfo endpoint
22-
- The scopes required to obtain user data
23-
- Client credentials (client ID and secret)
19+
- `opSettings`. An Agama map that specify the settings to be able to interact with the external OP
20+
- `uidPrefix`. A string value used for user provisioning: the user inserted in local DB will have an `uid` equal to the concatenation of `uidPrefix` and the `sub` released by the external OP. This param can be omitted or set to `null` if no prefixing is desired
2421

25-
In this process, you will be required to supplied a redirect URI, use the following: `https://<jans-server-host-name>/jans-auth/fl/callback`
22+
### OP settings
2623

27-
## Project deployment
24+
The structure of `opSettings` is as follows:
2825

29-
- Copy (SCP/SFTP) the gama file of this project to a location in your Jans server
30-
- Connect (SSH) to your Jans Server and open TUI: `python3 /opt/jans/jans-cli/jans_cli_tui.py`
31-
- Navigate to the Agama tab and then select "Upload project". Choose the gama file
32-
- Wait for about one minute and then select the row in the table corresponding to this project
33-
- Press `d` and ensure there were not deployment errors
34-
- Pres ESC to close the dialog
26+
|Name|Description|Notes|
27+
|-|-|-|
28+
|`host`|Location of the identity provider, eg. `https://my.idp.co`|Required if DCR is enabled, see below|
29+
|`dcr`|The `openid` flow can make use of Dynamic Client Registration (DCR) - a feature some OPs provide|Required|
30+
|`oauth`|A map following the same structure of [oauthParams](#authzcodewithuserinfo-and-authzcode)||
3531

36-
## Project configuration
32+
Regarding oauth map, **not all fields** marked as required are necessary when DCR is enabled. It suffices to supply `scopes`.
3733

38-
- Still with the row highlighted, press `c` and choose to export the sample configuration to a file
39-
- Edit a copy of the file according to the OP settings formerly grabbed. They should go under the `io.jans.inbound.openid` section
40-
- Still with the row highlighted, press `c` and choose to import configuration. Supply the file just edited
34+
Here is a minimalistic value that can be supplied for `opSettings` when DCR is supported by the external OP:
4135

42-
## Testing
36+
```
37+
{
38+
host: "https://my.idp.co",
39+
dcr: { enabled: true, useCachedClient: true },
40+
oauth: { scopes: [ "openid" ] }
41+
}
42+
```
4343

44-
Configure the required in your Jans Server to be able to launch an authentication flow. Actual details may vary but you can resort to a handy browser extension called [jans-tarp](https://github.com/JanssenProject/jans/tree/main/demos/jans-tarp) that will save you a good amount of work.
44+
### DCR settings
4545

46-
When testing ensure the following parameters are present in the authorization request:
46+
The structure of `dcr` is as follows:
47+
48+
|Name|Description|Notes|
49+
|-|-|-|
50+
|`enabled`|A boolean value indicating if DCR will be used for the external OP|Required<!--Optional. `false` value assumed if missing-->|
51+
|`useCachedClient`|Once the first client registration takes place, no more registration attempts will be made until the client is about to expire. Set this to `true` to force registration every time `openid` flow is launched|Required|
52+
53+
54+
## `AuthzCodeWithUserInfo` and `AuthzCode`
55+
56+
Each of these flows receive an input parameter (`oauthParams`) to drive their behavior. `oauthParams` is expected to be an Agama map with the following structure:
57+
58+
|Name|Description|Notes|
59+
|-|-|-|
60+
|`authzEndpoint`|The authorization endpoint as in section 3.1 of [RFC 7649](https://www.ietf.org/rfc/rfc6749)|Required|
61+
|`tokenEndpoint`|The token endpoint as in section 3.2 of [RFC 7649](https://www.ietf.org/rfc/rfc6749)|Required|
62+
|`userInfoEndpoint`|The endpoint where profile data can be retrieved. This is not part of the OAuth2 specification|Optional|
63+
|`clientId`|The identifier of the client to use, see section 1.1 and 2.2 of [RFC7649](https://www.ietf.org/rfc/rfc6749). This client is assumed to be *confidential* as in section 2.1|Required|
64+
|`clientSecret`|Secret associated to the client|Required|
65+
|`scopes`|An array of strings that represent the scopes of the access tokens to retrieve|Required|
66+
|`redirectUri`|Redirect URI as in section 3.1.2 of [RFC 7649](https://www.ietf.org/rfc/rfc6749)|Optional (auto filled when missing)|
67+
|`clientCredsInRequestBody`|`true` indicates the client authenticates at the token endpoint by including the credentials in the body of the request, otherwise, HTTP Basic authentication is assumed. See section 2.3.1 of [RFC 7649](https://www.ietf.org/rfc/rfc6749)|Optional. `false` is assumed if not supplied|
68+
|`custParamsAuthReq`|An Agama map (keys and values expected to be strings) with extra parameters to pass to the authorization endpoint if desired|Optional|
69+
|`custParamsTokenReq`|An Agama map (keys and values expected to be strings) with extra parameters to pass to the token endpoint if desired|Optional|
70+
71+
## FAQ
72+
73+
74+
### I don't use DCR and I am asked to provide a redirect URI in order to get a client ID/Secret
75+
76+
Supply the following: `https://<jans-server-host-name>/jans-auth/fl/callback`
77+
78+
### What methods for token endpoint authentication are supported?
79+
80+
Only `client_secret_basic` and `client_secret_post` are supported
4781

48-
- `acr_values=agama`
49-
- `agama_flow=io.jans.inbound.openid`

code/io.jans.inbound.oauth2.AuthzCodeWithUserInfo.flow

Lines changed: 0 additions & 16 deletions
This file was deleted.

code/io.jans.inbound.openid.flow

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
// OAuth 2.0 code flow
2-
Flow io.jans.inbound.oauth2.AuthzCode
1+
Flow org.gluu.inbound.oauth2.AuthzCode
32
Basepath ""
43
Inputs oauthParams
54
When oauthParams.redirectUri is null
6-
issuer = Call io.jans.util.NetworkUtils#urlBeforeContextPath
7-
list = [ issuer, "/jans-auth/fl/callback" ]
8-
oauthParams.redirectUri = Call java.lang.String#join "" list
9-
codeGrantUtil = Call io.jans.inbound.oauth2.CodeGrantUtil#new oauthParams
5+
// Obtain redirect uri based on hostname from HTTP url
6+
oauthParams.redirectUri = Call org.gluu.util.NetworkUtils#makeRedirectUri
7+
// Instantiate code grant utility
8+
codeGrantUtil = Call org.gluu.inbound.oauth2.CodeGrantUtil#new oauthParams
109
Log "@info Creating an authorization request"
1110
url = Call codeGrantUtil makeAuthzRequest
1211
state = url.second
1312
url = url.first
1413
Log "@info Redirecting to external site"
1514
responseParams = RFAC url
1615
Log "@info Browser taken back to redirect URI"
16+
// Parse code presented at callback uri
1717
code = Call codeGrantUtil parseCode responseParams state
1818
response = Call codeGrantUtil getTokenResponse code
1919
Log "@info An access token has been obtained"
20-
obj = { success: true, data: response }
21-
Finish obj
20+
outcome = { success: true, data: response }
21+
Finish outcome

0 commit comments

Comments
 (0)