Skip to content

Commit

Permalink
fix: #2201 (#3451)
Browse files Browse the repository at this point in the history
  • Loading branch information
maduvena authored Dec 29, 2022
1 parent 0df2083 commit 0417c2a
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 44 deletions.
4 changes: 2 additions & 2 deletions docs/admin/developer/interception-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ request authorization for each scope, and display the respective scope descripti
1. [Dynamic Scopes](./scripts/dynamic-scope.md) : Enables admin to generate scopes on the fly, for example by
calling external APIs
1. ID Generator
1. [Update Token](./scripts/update-token.md)
1. [Update Token](./scripts/update-token.md) : Enables transformation of claims and values in id_token, Access token and Refresh tokens; allows the setting of token lifetime; allows the addition or removal of scopes to / from tokens; allows the addition of audit logs each time a token is created.
1. Session Management
1. SCIM
1. [Introspection](./scripts/introspection.md)
1. [Introspection](./scripts/introspection.md) : Introspection scripts allows to modify response of Introspection Endpoint spec and present additional meta information surrounding the token.
1. [Post Authentication](./scripts/post-authentication.md)
1. Resource Owner Password Credentials
1. UMA 2 RPT Authorization Policies
Expand Down
191 changes: 160 additions & 31 deletions docs/admin/developer/managed-beans.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,37 @@
tags:
- administration
- developer
- bean
- CdiUtil
---

## Ready-to-use code in Custom script:
Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans. The most important aspects of business logic are implemented through a set of beans some of which are listed below:
Jans-auth server uses Weld 3.0 (JSR-365 aka CDI 2.0) for managed beans.
The most important aspects of business logic are implemented through a set of beans

### 1. [AuthenticationService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/AuthenticationService.java)
### Obtaining a bean inside a custom script:
[CdiUtil](https://github.com/JanssenProject/jans/blob/main/jans-core/service/src/main/java/io/jans/service/cdi/util/CdiUtil.java) used to obtain managed beans inside a custom script.

Relevant methods:

|Signature|Description|
|-|-|
|<T> T bean(Class<T> clazz)|Gets the managed bean belonging to the class passed as parameter|

Usage (jython code):
Suppose UserService and AuthenticationService beans have to be referenced in the code, it can be done as below:

```
from org.gluu.oxauth.service import UserService
from org.gluu.oxauth.service import AuthenticationService
...
userService = CdiUtil.bean(UserService)
authenticationService = CdiUtil.bean(AuthenticationService)
```

## Commonly used beans:

### 1. [AuthenticationService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/AuthenticationService.java)

Allows to authenticate a user or obtain the current authenticated user
<br/>
Expand All @@ -19,17 +44,28 @@ Relevant methods:
|`boolean authenticate(String userName, String password)`|Performs authentication for the user whose identifier (`userName`) is passed as parameter. The `password` supplied must be the correct password of the user in question|
|`User getAuthenticatedUser()`|Returns a representation of the currently authenticated user. `null` if no user is currently authenticated. See [User](#class-user) data object|

### 2. [Authenticator](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/auth/Authenticator.java)
This class is mainly used in facelets templates for authentication flows to proceed in the sequence of steps.
Relevant methods:
Usage:
```
|Signature|Description|
|-|-|
|boolean authenticate()|Makes the authentication flow proceed by calling the `authenticate` method of the custom script|
|String prepareAuthenticationForStep()|Makes the authentication flow proceed by calling the `prepareForStep` method of the custom script|
from io.jans.as.server.service import AuthenticationService
...
### 3. [UserService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/UserService.java)
Allows CRUD of users in the local persistence.
#1. authenticate a user using username and password
authenticationService = CdiUtil.bean(AuthenticationService)
logged_in = authenticationService.authenticate(user_name, user_password)
# 2. authenticate method without passing password parameter
logged_in = authenticationService.authenticate(user_name, user_password)
#3. obtain an authenticated user
user = authenticationService.getAuthenticatedUser()
userName = user.getUserId()
emailIds = user.getAttribute("oxEmailAlternate")
```

### 2. [UserService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/service/common/UserService.java)
Allows CRUD operations for users to the local persistence.

Relevant methods:

Expand All @@ -49,13 +85,63 @@ Relevant methods:
|`void setCustomAttribute(User user, String attributeName, String attributeValue)`|Sets the value of the attribute `attributeName` with the single value `attributeValue` for the user representation passes as parameter. This method does not persist changes|
|`User updateUser(User user)`|Updates the user represented by `user` object in the database|

#### Usage

#### a. Add a user
```
from io.jans.as.common.service.common import UserService
...
new_user = User()
new_user.setAttribute("uid", user_email, True)
new_user.setAttribute("givenName", username, True)
new_user.setAttribute("displayName", username, True)
new_user.setAttribute("sn", "-", True)
new_user.setAttribute("mail", user_email, True)
new_user.setAttribute("gluuStatus", "active", True)
new_user.setAttribute("password", user_password)
new_user = CdiUtil.bean(UserService).addUser(new_user, True)
```
#### b. Add user attributes
```
userObject = userService.addUserAttribute(user_name, "oxExternalUid", cert_user_external_uid)
```
#### c. Get User
```
# example 1 - get User by userId
user = userService.getUser(user_name)
# example 2 - get User by User-Id only if attribute oxExternalUid is populated
user = userService.getUser(user_name, "oxExternalUid")
customAttributeValue = userService.getCustomAttribute(user, "oxExternalUid")
```
#### d. Get specific User attribute
```
status_attribute_value = userService.getCustomAttribute(find_user_by_uid, "gluuStatus")
```
#### e. Replace user attributes
```
userService.replaceUserAttribute(user_name, "oxOTPCache", cachedOTP, localTotpKey)
```
#### f. Remove user attribute
```
userService.removeUserAttribute(user.getUserId(),"oxTrustExternalId", "wwpass:%s"%puid)
```
#### g. Update users
```
found_user = userService.getUser(user_name)
found_user.setAttribute("userPassword", new_password)
userService.updateUser(found_user)
```

### 4. [User](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/common/src/main/java/io/jans/as/common/model/common/User.java)
A class employed to represent a user entry in the persistence. Provides getters and setters to retrieve and assign value(s) for attributes

### 5. [CustomAttribute](https://github.com/JanssenProject/jans/blob/main/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomAttribute.java)
### 5. [CustomAttribute](https://github.com/JanssenProject/jans/blob/main/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomAttribute.java)
A class that models an attribute. An attribute has a name and a collection of associated values

### 6. [Identity](https://github.com/JanssenProject/jans/blob/main/jans-core/service/src/main/java/io/jans/model/security/Identity.java)
### 6. [Identity](https://github.com/JanssenProject/jans/blob/main/jans-core/service/src/main/java/io/jans/model/security/Identity.java)
Mainly used to carry data between steps of authentication flows.

|Signature|Description|
Expand All @@ -64,7 +150,7 @@ Mainly used to carry data between steps of authentication flows.
|`void setWorkingParameter(String name, Object value)`|Binds data to a name for further use in an authentication flow. Recommended values to store are `String`s|
|`SessionId getSessionId()`|Retrieves a reference to the associated server session object, see [SessionId](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/SessionId.java)|

### 7. HttpService: [HttpService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/net/HttpService.java)
### 7. HttpService: [HttpService](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/net/HttpService.java)

Provides utility methods to execute HTTP requests, manipulate responses, etc

Expand All @@ -76,7 +162,7 @@ Relevant methods:
|`HttpServiceResponse executeGet(HttpClient httpClient, String requestUri)`|Perform a GET on the URI requested. Returns an instance of [io.jans.as.server.model.net.HttpServiceResponse](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/model/net/HttpServiceResponse.java) (a wrapper on `org.apache.http.HttpResponse`)|
|`byte[] getResponseContent(HttpResponse httpResponse)`|Consumes the bytes of the associated response. Returns `null` if the response status code is not 200 (OK)|

### 8. [CacheService](https://github.com/JanssenProject/jans/blob/main/jans-core/cache/src/main/java/io/jans/service/CacheService.java)
### 8. [CacheService](https://github.com/JanssenProject/jans/blob/main/jans-core/cache/src/main/java/io/jans/service/CacheService.java)
Provides a unified means to interact with the underlying cache provider configured in the Jans-auth Server

Relevant methods:
Expand All @@ -98,7 +184,7 @@ Relevant methods:
|`void redirectToExternalURL(String url)`|Redirects the user's browser to the URL passed as parameter|
|`String encodeParameters(String url, Map<String, Object> parameters)`|Builds a URL by appending query parameters as supplied in `parameters` map. Every value in the map is properly URL-encoded|

### 10. [FacesMessages](https://github.com/JanssenProject/jans/blob/main/jans-core/jsf-util/src/main/java/io/jans/jsf2/message/FacesMessages.java)
### 10. [FacesMessages](https://github.com/JanssenProject/jans/blob/main/jans-core/jsf-util/src/main/java/io/jans/jsf2/message/FacesMessages.java)
Allows manipulation of JSF context messages

Relevant methods:
Expand All @@ -111,28 +197,48 @@ Relevant methods:
|`void setKeepMessages()`|Sets the "keep messages" property of the JSF flash|


### 11. [CdiUtil](https://github.com/JanssenProject/jans/blob/main/jans-core/service/src/main/java/io/jans/service/cdi/util/CdiUtil.java) : Allows to obtain references of managed beans. This is particularly useful in custom scripts
### 11. [StringHelper](https://github.com/JanssenProject/jans/blob/main/jans-core/util/src/main/java/io/jans/util/StringHelper.java)
Provides many utility methods that often arise in the manipulation of Strings
Usage:

Relevant methods:
```
from io.jans.util import StringHelper
```

|Signature|Description|
|-|-|
|<T> T bean(Class<T> clazz)|Gets the managed bean belonging to the class passed as parameter|
1. #### isNotEmptyString
```
if StringHelper.isNotEmptyString(user_name):
# do something
```

Example (jython code):
2. #### equalsIgnoreCase
```
if StringHelper.equalsIgnoreCase(authentication_mode, "one_step"):
# do something
```

3. #### isEmpty
```
from org.gluu.oxauth.service import UserService
from org.gluu.oxauth.service import AuthenticationService
...
userService = CdiUtil.bean(UserService)
authenticationService = CdiUtil.bean(AuthenticationService)
if StringHelper.isEmpty(auth_method):
# do something
```

### 12. [StringHelper](https://github.com/JanssenProject/jans/blob/main/jans-core/util/src/main/java/io/jans/util/StringHelper.java)
Provides many utility methods that often arise in the manipulation of Strings
4. #### split
```
allowedClientsListArray = StringHelper.split(allowedClientsList, ",")
```

### 13. [EncryptionService](https://github.com/JanssenProject/jans/blob/main/jans-scim/service/src/main/java/io/jans/scim/service/EncryptionService.java)
5. #### toLowerCase
```
remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i])
```
6. #### base64urlencode
```
StringUtils.base64urlencode(input);
```


### 13. [EncryptionService](https://github.com/JanssenProject/jans/blob/main/jans-scim/service/src/main/java/io/jans/scim/service/EncryptionService.java)
Allows to encrypt/decrypt strings using a 3DES cipher whose salt is found in `/etc/jans/conf/salt`

Relevant methods:
Expand All @@ -141,4 +247,27 @@ Relevant methods:
|-|-|
|String decrypt(String encryptedString)|Decrypts the encrypted string supplied|
|Properties decryptAllProperties(Properties connectionProperties)|Returns a `java.util.Properties` object with all decrypted values found in `connectionProperties`|
|`String encrypt(String unencryptedString)`|Encrypts the string supplied|
|`String encrypt(String unencryptedString)`|Encrypts the string supplied|

#### Usage:
```
from io.jans.as.common.service.common import EncryptionService
....
encryptionService = CdiUtil.bean(EncryptionService)
pwd_decrypted = encryptionService.decrypt("stringtobedecrypted")
```

14. [Base64Util](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/model/src/main/java/io/jans/as/model/util/Base64Util.java)

Usage:

```
from io.jans.as.model.util import Base64Util
....
Base64Util.base64urldecodeToString(input_string)
Base64Util.base64urlencode(input_string.encode('utf-8')));
```
88 changes: 88 additions & 0 deletions docs/admin/developer/scripts/person-authentication-faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
tags:
- administration
- developer
- scripts
- acr_values_supported
- 2FA
- PersonAuthenticationType
- acr
- weld
- error messsages
- redirection
---


### 1. Display error messages on a web page?
1.[FacesMessages](https://github.com/JanssenProject/jans/blob/main/jans-core/jsf-util/src/main/java/io/jans/jsf2/message/FacesMessages.java) bean is used for this purpose.
```
from org.jans.jsf2.message import FacesMessages
from org.jans.service.cdi.util import CdiUtil
from javax.faces.application import FacesMessage
...

facesMessages = CdiUtil.bean(FacesMessages)
facesMessages.setKeepMessages()
facesMessages.add(FacesMessage.SEVERITY_ERROR, "Please enter a valid username")

```
2. The error will appear in the associated template using the following markup:
```
...
<h:messages />
...
```
See an example [here](https://github.com/JanssenProject/jans/blob/685a1593fb53e2310cfa38fcd49db94f3453042f/jans-auth-server/server/src/main/webapp/WEB-INF/incl/layout/template.xhtml#L41)

### 2. Redirection to a third party application for authentication

For user authentication or consent gathering, there might be a need to redirect to a third party application to perform some operation and return the control back to authentication steps of the custom script. Please apply these steps to a person authentication script in such a scenario:

- Return from def getPageForStep(self, step, context), a page /auth/method_name/redirect.html ; with content similar to the code snippet below -
```
def getPageForStep(self, step, context):
return "/auth/method_name/redirect.html"
```
- Contents of redirect.xhtml should take the flow to prepareForStep method
```
...
<f:metadata>
<f:viewAction action="#{authenticator.prepareForStep}" if="#{not identity.loggedIn}" />
</f:metadata>
```
- In method prepareForStep prepare data needed for redirect and perform the redirection to the external service.
```
def prepareForStep(self, step, context):
.....
facesService = CdiUtil.bean(FacesService)
facesService.redirectToExternalURL(third_party_URL )

return True
```
- In order to resume flow after the redirection, invoke a similar URL to https://my.gluu.server/postlogin.htm?param=123 from the third party app which takes the flow back to the authenticate method of the custom script.
So create an xhtml page postlogin.xhtml which will look like this :
```
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core">

<f:view transient="true" contentType="text/html">
<f:metadata>
<f:viewAction action="#{authenticator.authenticateWithOutcome}" />
</f:metadata>
</f:view>

</html>
```
The `<f:viewAction action="#{authenticator.authenticateWithOutcome}" />` in step 4 takes us to the authenticate method inside the custom script `def authenticate(self, configurationAttributes, requestParameters, step):`. Here you can
- use parameters from request
```
param = ServerUtil.getFirstValue(requestParameters, "param-name"))
```
- perform the `state` check (state : Opaque value used to maintain state between the request and the callback.)

- finally, return true or false from this method.

3.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ tags:
- administration
- developer
- scripts
- PersonAuthenticationType
- authentication
- authentication workflow
---

## Person Authentication interface
Expand Down Expand Up @@ -55,8 +58,8 @@ Pseudo code:
|7.| `getAuthenticationMethodClaims` | Array of strings that are identifiers for authentication methods used in the authentication. In OpenID Connect, if the identity provider supplies an "amr" claim in the ID Token resulting from a successful authentication, the relying party can inspect the values returned and thereby learn details about how the authentication was performed.|
|8.| `isValidAuthenticationMethod`| This method is used to check if the authentication method is in a valid state. For example we can check there if a 3rd party mechanism is available to authenticate users. As a result it should either return True or False.|
|9.| `getAlternativeAuthenticationMethod` | This method is called only if the current authentication method is in an invalid state. Hence authenticator calls it only if isValidAuthenticationMethod returns False. As a result it should return the reserved authentication method name.|
|10. `getLogoutExternalUrl` | Returns the 3rd-party URL that is used to end session routines. The control from this Third party URL should re-direct user back to /oxauth/logout.htm again with empty URL query string. Jans-Auth server will then continue of the extended logout flow, restore the original URL query string, and send user to `/jans-auth/end_session` to complete it.|
|11. `logout` | This method is not mandatory. It can be used in cases when you need to execute specific logout logic in the authentication script when jans-auth receives an end session request to the /oxauth/logout.htm endpoint (which receives the same set of parameters than the usual end_session endpoint). This method should return True or False; when False jans-auth stops processing the end session request workflow.|
|10. | `getLogoutExternalUrl` | Returns the 3rd-party URL that is used to end session routines. The control from this Third party URL should re-direct user back to /oxauth/logout.htm again with empty URL query string. Jans-Auth server will then continue of the extended logout flow, restore the original URL query string, and send user to `/jans-auth/end_session` to complete it.|
|11. |`logout` | This method is not mandatory. It can be used in cases when you need to execute specific logout logic in the authentication script when jans-auth receives an end session request to the /oxauth/logout.htm endpoint (which receives the same set of parameters than the usual end_session endpoint). This method should return True or False; when False jans-auth stops processing the end session request workflow.|

#### Objects
| Object name | Object description |
Expand All @@ -65,7 +68,6 @@ Pseudo code:
|`SimpleCustomProperty`| Map of configuration properties. [Reference](https://github.com/JanssenProject/jans/blob/main/jans-core/util/src/main/java/io/jans/model/SimpleCustomProperty.java) |
|usageType|[AuthenticationScriptUsageType](https://github.com/JanssenProject/jans/blob/main/jans-core/util/src/main/java/io/jans/model/AuthenticationScriptUsageType.java)|
|step|Integer indicating step number|
|step|Integer indicating step number|
|requestParameters|Request parameters stored as Map<String, String[]>|


Expand Down
Loading

0 comments on commit 0417c2a

Please sign in to comment.