Skip to content

Commit

Permalink
docs: add combined registration + authn flow #1749 (#1843)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgomer2001 committed Jul 21, 2022
1 parent 723922a commit 061ab38
Show file tree
Hide file tree
Showing 12 changed files with 338 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/admin/developer/agama/basic/io.jans.flow.sample.basic
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Repeat 3 times max
When obj.success is true
Finish obj.uid

Finish false
Finish false
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="${webCtx.contextPath}/servlet/favicon" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
#logo {
max-height: 3.25rem;
margin: 0.5rem;
}
</style>
</head>
<body>

<div class="d-flex flex-column align-items-center justify-content-between min-vh-100 w-100">
<header class="d-flex w-100 justify-content-between border-bottom">
<img id="logo" src="https://gluu.org/wp-content/uploads/2021/02/janssen-project-transparent-630px-182px-300x86.png" />
</header>

<div class="row col-sm-10 col-md-5 my-3">

<div class="d-flex flex-column align-items-center border border-1 rounded p-5">
<p class="fs-4 mb-5" align="center">An account has been created for <span class="fw-bold">${username}</span></p>

<form method="post" enctype="application/x-www-form-urlencoded">
<input type="submit" class="btn btn-success px-4" value="Proceed to login">
</form>
</div>

</div>
<footer class="d-flex flex-column align-items-center w-100 pb-2">
<hr class="w-75">
</footer>
</div>

</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Flow io.jans.flow.sample.otp.emailWithRegistration
Basepath "samples/otp-email-registration"

obj = Trigger io.jans.flow.sample.otp.email
Override templates "samples/basic/login.ftlh" ""

When obj.aborted is true
//Take the registration path
obj = Trigger io.jans.flow.sample.registration
Override templates "samples/registration/confirmation.ftlh" ""

When obj.success is true
//Use otp-email registration as is
obj = Trigger io.jans.flow.sample.otp.email

Finish obj
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions docs/admin/developer/agama/otp-email-registration/login.ftlh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="${webCtx.contextPath}/servlet/favicon" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
#logo {
max-height: 3.25rem;
margin: 0.5rem;
}
</style>
</head>
<body>

<div class="d-flex flex-column align-items-center justify-content-between min-vh-100 w-100">
<header class="d-flex w-100 justify-content-between border-bottom">
<img id="logo" src="https://gluu.org/wp-content/uploads/2021/02/janssen-project-transparent-630px-182px-300x86.png" />
</header>

<div class="row col-sm-10 col-md-5 mb-5 pb-5">

<div class="border border-1 rounded mb-5 p-5">
<p class="fs-4 mb-5">Welcome</p>

<#if !(success!true)>
<p class="fs-6 text-danger mb-3">${msgs["login.errorMessage"]}</p>
</#if>

<form method="post" enctype="application/x-www-form-urlencoded">
<div class="mb-3 row">
<label for="username" class="col-md-3 col-form-label">${msgs["login.username"]}</label>
<div class="col-md-9">
<input type="text" class="form-control" name="username" id="username" value="${uid!}" required>
</div>
</div>
<div class="mb-3 row">
<label for="password" class="col-md-3 col-form-label">${msgs["login.password"]}</label>
<div class="col-md-9">
<input type="password" class="form-control" id="password" name="password">
</div>
</div>
<div class="mb-3 row">
<div class="col-md-12 d-flex justify-content-end">
<input type="submit" class="btn btn-success px-4" value="${msgs["login.login"]}">
</div>
</div>
</form>
<form method="post" enctype="application/x-www-form-urlencoded">
<div class="row d-flex justify-content-center">
<button type="submit" class="btn btn-link" id="_abort" name="_abort" value="">
Don't have an account?
</button>
</div>
</form>
</div>

</div>
<footer class="d-flex flex-column align-items-center w-100 pb-2">
<hr class="w-75">
</footer>
</div>

</body>
</html>
Binary file modified docs/admin/developer/agama/otp-email/otp_email.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions docs/admin/developer/agama/registration/RegistrationUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.jans.agama.samples;

import io.jans.agama.engine.script.LogUtils;
import io.jans.as.common.model.common.User;
import io.jans.as.server.service.UserService;
import io.jans.service.cdi.util.CdiUtil;

import java.util.Date;

public class RegistrationUtil {

public static String register(String givenName, String userName, String password, String password2, String email) {

UserService uss = CdiUtil.bean(UserService.class);
User user = uss.getUser(userName, "uid");

if (user != null) return "This account already exists";

if (!email.matches(".+@.+")) return "Invalid e-mail address";

if (!password2.equals(password)) return "Passwords do not match";

user = new User();
user.setUserId(userName);
user.setAttribute("givenName", givenName);
user.setAttribute("userPassword", password);
user.setAttribute("mail", email);

try {
uss.addUser(user, true);
} catch (Exception e) {
LogUtils.log("@e ", e.getMessage());
return "An unexpected error occurred";
}
return null;

}
}
39 changes: 39 additions & 0 deletions docs/admin/developer/agama/registration/confirmation.ftlh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="${webCtx.contextPath}/servlet/favicon" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
#logo {
max-height: 3.25rem;
margin: 0.5rem;
}
</style>
</head>
<body>

<div class="d-flex flex-column align-items-center justify-content-between min-vh-100 w-100">
<header class="d-flex w-100 justify-content-between border-bottom">
<img id="logo" src="https://gluu.org/wp-content/uploads/2021/02/janssen-project-transparent-630px-182px-300x86.png" />
</header>

<div class="row col-sm-10 col-md-5 my-3">

<div class="d-flex flex-column align-items-center border border-1 rounded p-5">
<p class="fs-4 mb-5" align="center">An account has been created for <span class="fw-bold">${username}</span></p>

<form method="post" enctype="application/x-www-form-urlencoded">
<input type="submit" class="btn btn-success px-4" value="Continue">
</form>
</div>

</div>
<footer class="d-flex flex-column align-items-center w-100 pb-2">
<hr class="w-75">
</footer>
</div>

</body>
</html>
77 changes: 77 additions & 0 deletions docs/admin/developer/agama/registration/index.ftlh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="${webCtx.contextPath}/servlet/favicon" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
#logo {
max-height: 3.25rem;
margin: 0.5rem;
}
</style>
</head>
<body>

<div class="d-flex flex-column align-items-center justify-content-between min-vh-100 w-100">
<header class="d-flex w-100 justify-content-between border-bottom">
<img id="logo" src="https://gluu.org/wp-content/uploads/2021/02/janssen-project-transparent-630px-182px-300x86.png" />
</header>

<div class="row col-sm-10 col-md-5 my-3">

<div class="border border-1 rounded p-5">
<p class="fs-4 mb-5">Create your account</p>

<p class="fs-6 text-danger mb-4">${error!}</p>

<form method="post" enctype="application/x-www-form-urlencoded">
<div class="mb-3 row">
<label for="name" class="col-md-3 col-form-label">First name</label>
<div class="col-md-9">
<input type="text" class="form-control" name="name" id="name" value="${name!}" required>
</div>
</div>
<div class="mb-3 row">
<label for="username" class="col-md-3 col-form-label">Username</label>
<div class="col-md-9">
<input type="text" class="form-control" name="username" id="username"
value="${username!}" required>
</div>
</div>
<div class="mb-3 row">
<label for="pwd" class="col-md-3 col-form-label">Choose a password</label>
<div class="col-md-9">
<input type="password" class="form-control" id="pwd" name="pwd" required>
</div>
</div>
<div class="mb-3 row">
<label for="pwd2" class="col-md-3 col-form-label">Confirm password</label>
<div class="col-md-9">
<input type="password" class="form-control" id="pwd2" name="pwd2" required>
</div>
</div>
<div class="mb-3 row">
<label for="email" class="col-md-3 col-form-label">Your e-mail</label>
<div class="col-md-9">
<input type="email" class="form-control" id="email" name="email"
placeHolder="name@example.com" value="${email!}" required>
</div>
</div>
<div class="row">
<div class="col-md-12 d-flex justify-content-end">
<input type="submit" class="btn btn-success px-4" value="Register">
</div>
</div>
</form>
</div>

</div>
<footer class="d-flex flex-column align-items-center w-100 pb-2">
<hr class="w-75">
</footer>
</div>

</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Flow io.jans.flow.sample.registration
Basepath "samples/registration"

o = {}
Repeat 3 times max
o = RRF "index.ftlh" o
o.error = Call io.jans.agama.samples.RegistrationUtil#register o.name o.username o.pwd o.pwd2 o.email

When o.error is null
o.pwd = null
o.pwd2 = null

RRF "confirmation.ftlh" o
Finish true

Log "Error creating user %" o.error

Finish false
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 44 additions & 1 deletion docs/admin/developer/agama/samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This page provides some practical flow examples to help readers in their process of learning Agama. It is recommended to visit the quick start [guide](./quick-start.md) first.

!!! Warning
Do not deploy any of these flows to production.

## Basic authentication

This is the simplest form of authentication where end-users gain access to a protected resource (e.g. an application) by providing a valid username and password combination. In this example users will be given three attempts at most to supply valid credentials, otherwise an error page will be shown.
Expand Down Expand Up @@ -93,4 +96,44 @@ If the user presses the enter key when the focus is on the text field, the form

## Combined registration and authentication flow

TODO
In this flow features like [template overrides](./dsl-full.md#template-overrides) and [flow cancellation](./flows-lifecycle.md#cancellation) are leveraged to bring a more sophisticated authentication journey. A description follows:

- A login form (username/password) is shown with an auxiliary link to offer account registration

- If the registration link is clicked, the user is shown a page that prompts personal details in order to create an account

- Upon successful account creation, a "continue to login" page is presented

- The OTP authentication flow of the previous section is reused: a standard login form is shown and then the user is prompted to enter a passcode.

### Registration

For the purposes of registration, a small flow was created:

![registration](./registration/io.jans.flow.sample.registration.png)

Source code [here](./registration/io.jans.flow.sample.registration).

This flow is pretty simple and we are not going into the details here. Keep in mind the following:

- Upload [confirmation.ftlh](./registration/confirmation.ftlh) and [index.ftlh](./registration/index.ftlh) files to folder `/opt/jans/jetty/jans-auth/agama/ftl/samples/registration`

- Copy the file [RegistrationUtil.java](./registration/RegistrationUtil.java) to directory `/opt/jans/jetty/jans-auth/agama/io/jans/agama/samples`

- Keep this flow disabled. If used standalone, it will finish but no actual person will be authenticated. It is not designed to be used directly but by other flows.

### Main flow

![registration and authentication](./otp-email-registration/io.jans.flow.sample.otp.emailWithRegistration.png)

Source code [here](./otp-email-registration/io.jans.flow.sample.otp.emailWithRegistration).

This flow is short and powerful. To start it launches the [email OTP authentication](#email-otp-authentication) flow (line 4). However, instead of the `login.ftlh` template used internally by the basic flow, a different version is used (line 5). The new template is located in this flow's basepath, i.e. `samples/otp-email-registration`, and the file name does not change.

This new page simply adds a small link that reads "Don't have an account?" in a new HTML form. When clicked it will provoke the email-OTP flow to be aborted early and the condition at line 8 will be truthy. If that's not the case, the email-OTP flow will proceed as usual and the current flow will finish in the same way as email-OTP (line 16).

If email-OTP is aborted, the [registration flow](#registration) that we just saw is launched (line 9). Here the template `confirmation.ftlh` is overriden too (line 10). This new page changes the label of the button that is shown after an account has been created: originally the text is "Continue" but for the current flow, "Proceed to login" is a better fit.

If the registration flow finishes successfully (line 12), the email-OTP flow is triggered again (line 14) - this time without customizations. Then the user can supply his recently-created credentials to get past the basic authentication stage and finally move to the OTP challenge. Recall that via registration flow the user's e-mail address is already stored in the database.

Finally, the current flow finishes identically as email-OTP did (line 16).

0 comments on commit 061ab38

Please sign in to comment.