From 436697f1cd11fb2d309ad0a95e737f709826fb03 Mon Sep 17 00:00:00 2001 From: Safin Wasi <6601566+SafinWasi@users.noreply.github.com> Date: Fri, 23 Dec 2022 10:23:03 -0600 Subject: [PATCH] docs: add ropc script (#3397) * docs: ropc script * docs: corrected file name * docs: corrected ropc file name Co-authored-by: Sam Morris <36208047+shmorri@users.noreply.github.com> --- .../developer/scripts/post-authentication.md | 2 +- docs/admin/developer/scripts/ropc.md | 175 ++++++++++++++++++ docs/admin/developer/scripts/rpoc.md | 18 -- mkdocs.yml | 2 +- 4 files changed, 177 insertions(+), 20 deletions(-) create mode 100644 docs/admin/developer/scripts/ropc.md delete mode 100644 docs/admin/developer/scripts/rpoc.md diff --git a/docs/admin/developer/scripts/post-authentication.md b/docs/admin/developer/scripts/post-authentication.md index 1955fdcde7e..4ab2a063515 100644 --- a/docs/admin/developer/scripts/post-authentication.md +++ b/docs/admin/developer/scripts/post-authentication.md @@ -10,7 +10,7 @@ tags: After the browser has a session, if a person visits the website, the requesting party can obtain a code without the user having to authenticate or authorize. In some cases, it is desirable to insert custom business logic before granting the code or tokens from the authorization endpoint. Post Authentication script allows to force re-authentication or re-authorization (even if client is "Pre-authorized" or client authorization persistence is on). ## Interface -The consent gathering script implements the [PostAuthnType](https://github.com/JanssenProject/jans/blob/main/jans-core/script/src/main/java/io/jans/model/custom/script/type/postauthn/PostAuthnType.java) interface. This extends methods from the base script type in addition to adding new methods: +The post authentication script implements the [PostAuthnType](https://github.com/JanssenProject/jans/blob/main/jans-core/script/src/main/java/io/jans/model/custom/script/type/postauthn/PostAuthnType.java) interface. This extends methods from the base script type in addition to adding new methods: ### Inherited Methods diff --git a/docs/admin/developer/scripts/ropc.md b/docs/admin/developer/scripts/ropc.md new file mode 100644 index 00000000000..1db858c2238 --- /dev/null +++ b/docs/admin/developer/scripts/ropc.md @@ -0,0 +1,175 @@ +--- +tags: + - administration + - developer + - scripts +--- + +## Overview +Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.3)). + +The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via `context.setUser(user)`). + +## Interface +The ROPC script implements the [ResourceOwnerPasswordCredentialsType](https://github.com/JanssenProject/jans/blob/main/jans-core/script/src/main/java/io/jans/model/custom/script/type/owner/ResourceOwnerPasswordCredentialsType.java) interface. This extends methods from the base script type in addition to adding new method: + +### Inherited Methods +| Method header | Method description | +|:-----|:------| +| `def init(self, customScript, configurationAttributes)` | This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc | +| `def destroy(self, configurationAttributes)` | This method is called once to destroy events. It can be used to free resource and objects created in the `init()` method | +| `def getApiVersion(self, configurationAttributes, customScript)` | The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 | + +### New Methods +| Method header | Method description | +| `def authenticate(self, context)` | This method is called after normal ROPC authentication. This method can cancel normal authentication if it returns false and sets `context.setUser(null)` | + +### Objects +| Object name | Object description | +|:-----|:------| +|`customScript`| The custom script object. [Reference](https://github.com/JanssenProject/jans/blob/main/jans-core/script/src/main/java/io/jans/model/custom/script/model/CustomScript.java) | +|`configurationAttributes`| `configurationProperties` passed in when adding custom script. `Map configurationAttributes` | +|`SimpleCustomProperty`| Map of configuration properties. [Reference](https://github.com/JanssenProject/jans/blob/main/jans-core/util/src/main/java/io/jans/model/SimpleCustomProperty.java) | +| `context` | [Reference](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalResourceOwnerPasswordCredentialsContext.java) | + +## Use case: Basic ROPC authentication script + +This script has been adapted from the Gluu Server [sample ROPC script](https://github.com/GluuFederation/community-edition-setup/blob/version_4.4.0/static/extension/resource_owner_password_credentials/resource_owner_password_credentials.py) + +### Script Type: Python + +```python +from io.jans.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType +from io.jans.as.server.service import AuthenticationService +from io.jans.service.cdi.util import CdiUtil +from java.lang import String + +class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): + def __init__(self, currentTimeMillis): + self.currentTimeMillis = currentTimeMillis + + def init(self, customScript, configurationAttributes): + print "ROPC script. Initializing ..." + + self.usernameParamName = "username" + self.passwordParamName = "password" + + print "ROPC script. Initialized successfully" + + return True + + def destroy(self, configurationAttributes): + print "ROPC script. Destroying ..." + print "ROPC script. Destroyed successfully" + return True + + def getApiVersion(self): + return 11 + + # Returns True and set user into context when user authenticated succesfully + # Returns False when user not authenticated or it's needed to cancel notmal flow + def authenticate(self, context): + print "ROPC script. Authenticate" + deviceIdParam = context.getHttpRequest().getParameterValues("device_id") + if deviceIdParam != None and (deviceIdParam.length > 0 ): + result = deviceIdParam[0] == "device_id_1" + if not result: + return False + + # Set authenticated user in context + # context.setUser(user) + return True + + # Do generic authentication in other cases + authService = CdiUtil.bean(AuthenticationService) + + username = context.getHttpRequest().getParameter(self.usernameParamName) + password = context.getHttpRequest().getParameter(self.passwordParamName) + result = authService.authenticate(username, password) + if not result: + print "ROPC script. Authenticate. Could not authenticate user '%s' " % username + return False + + context.setUser(authService.getAuthenticatedUser()) + + return True +``` + +### Script Type: Java +```java +import java.util.Map; + +import io.jans.model.SimpleCustomProperty; +import io.jans.model.custom.script.model.CustomScript; +import io.jans.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType; +import io.jans.service.custom.script.CustomScriptManager; +import io.jans.as.server.service.AuthenticationService; +import io.jans.service.cdi.util.CdiUtil; +import io.jans.as.server.service.external.context.ExternalResourceOwnerPasswordCredentialsContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResourceOwnerPasswordCredentials implements ResourceOwnerPasswordCredentialsType { + + private static final Logger log = LoggerFactory.getLogger(CustomScriptManager.class); + + private final String usernameParamName = "username"; + private final String passwordParamName = "password"; + + @Override + public boolean init(Map configurationAttributes) { + log.info("ROPC Script. Initializing..."); + log.info("ROPC Script. Initialized"); + return true; + } + + @Override + public boolean init(CustomScript customScript, Map configurationAttributes) { + log.info("ROPC Script. Initializing..."); + log.info("ROPC Script. Initialized"); + return true; + } + + @Override + public boolean destroy(Map configurationAttributes) { + log.info("ROPC Script. Destroying..."); + log.info("ROPC Script. Destroyed."); + return true; + } + + @Override + public int getApiVersion() { + return 11; + } + + @Override + public boolean authenticate(Object context) { + log.info("ROPC script. Authenticate"); + ExternalResourceOwnerPasswordCredentialsContext ropcContext = (ExternalResourceOwnerPasswordCredentialsContext) context; + String[] deviceIdParam = ropcContext.getHttpRequest().getParameterValues("device_id"); + if(deviceIdParam != null && deviceIdParam.length > 0) { + boolean result = deviceIdParam[0] == "device_id_1"; + if (!result) { + return false; + } + // Set authenticated user in context + // context.setUser(user) + return true; + } + // generic authentication in other cases + + AuthenticationService authService = CdiUtil.bean(AuthenticationService.class); + String username = ropcContext.getHttpRequest().getParameter(usernameParamName); + String password = ropcContext.getHttpRequest().getParameter(passwordParamName); + boolean result = authService.authenticate(username, password); + if(!result) { + log.info("ROPC script. Authenticate. Could not authenticate " + username); + return false; + } + ropcContext.setUser(authService.getAuthenticatedUser()); + return true; + } + +} +``` diff --git a/docs/admin/developer/scripts/rpoc.md b/docs/admin/developer/scripts/rpoc.md deleted file mode 100644 index 36fd0dd6bbf..00000000000 --- a/docs/admin/developer/scripts/rpoc.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -tags: - - administration - - developer - - scripts ---- - -## This content is in progress - -The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. - -## Have questions in the meantime? - -While this documentation is in progress, you can ask questions through [GitHub Discussions](https://github.com/JanssenProject/jans/discussion) or the [community chat on Gitter](https://gitter.im/JanssenProject/Lobby). Any questions you have will help determine what information our documentation should cover. - -## Want to contribute? - -If you have content you'd like to contribute to this page in the meantime, you can get started with our [Contribution guide](https://docs.jans.io/head/CONTRIBUTING/). \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 89dfa5546cd..9d2312a2774 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -374,7 +374,7 @@ nav: - 'Consent Gathering': 'admin/developer/scripts/consent-gathering.md' - 'Post Authentication': 'admin/developer/scripts/post-authentication.md' - 'id_token': 'admin/developer/scripts/id-token.md' - - 'Resource Owner Password Credentials': 'admin/developer/scripts/rpoc.md' + - 'Resource Owner Password Credentials': 'admin/developer/scripts/ropc.md' - 'CIBA End User Notification': 'admin/developer/scripts/ciba.md' - 'OpenID Configuration': 'admin/developer/scripts/openid-config.md' - 'Dynamic Scope': 'admin/developer/scripts/dynamic-scope.md'