Browse Source

Update web ui design for demo-authorizationserver

Issue gh-1196
pull/1210/head
Joe Grandja 3 years ago
parent
commit
4175effadd
  1. 4
      samples/demo-authorizationserver/samples-demo-authorizationserver.gradle
  2. 18
      samples/demo-authorizationserver/src/main/java/sample/web/DefaultErrorController.java
  3. 6
      samples/demo-authorizationserver/src/main/java/sample/web/DeviceController.java
  4. 32
      samples/demo-authorizationserver/src/main/resources/static/assets/css/signin.css
  5. 13
      samples/demo-authorizationserver/src/main/resources/static/assets/css/style.css
  6. BIN
      samples/demo-authorizationserver/src/main/resources/static/assets/img/devices.png
  7. BIN
      samples/demo-authorizationserver/src/main/resources/static/assets/img/github.png
  8. BIN
      samples/demo-authorizationserver/src/main/resources/static/assets/img/google.png
  9. 20
      samples/demo-authorizationserver/src/main/resources/templates/access-denied.html
  10. 33
      samples/demo-authorizationserver/src/main/resources/templates/activate.html
  11. 25
      samples/demo-authorizationserver/src/main/resources/templates/activated.html
  12. 62
      samples/demo-authorizationserver/src/main/resources/templates/consent.html
  13. 33
      samples/demo-authorizationserver/src/main/resources/templates/device-activate.html
  14. 25
      samples/demo-authorizationserver/src/main/resources/templates/device-activated.html
  15. 31
      samples/demo-authorizationserver/src/main/resources/templates/error.html
  16. 55
      samples/demo-authorizationserver/src/main/resources/templates/login.html

4
samples/demo-authorizationserver/samples-demo-authorizationserver.gradle

@ -21,8 +21,8 @@ dependencies { @@ -21,8 +21,8 @@ dependencies {
implementation "org.springframework.boot:spring-boot-starter-jdbc"
implementation project(":spring-security-oauth2-authorization-server")
implementation "org.webjars:webjars-locator-core"
implementation "org.webjars:bootstrap:3.4.1"
implementation "org.webjars:jquery:3.4.1"
implementation "org.webjars:bootstrap:5.2.3"
implementation "org.webjars:jquery:3.6.4"
runtimeOnly "com.h2database:h2"
testImplementation "org.springframework.boot:spring-boot-starter-test"

18
samples/demo-authorizationserver/src/main/java/sample/web/DefaultErrorController.java

@ -15,15 +15,13 @@ @@ -15,15 +15,13 @@
*/
package sample.web;
import java.util.Map;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @author Steve Riesenberg
@ -33,12 +31,16 @@ import org.springframework.web.servlet.ModelAndView; @@ -33,12 +31,16 @@ import org.springframework.web.servlet.ModelAndView;
public class DefaultErrorController implements ErrorController {
@RequestMapping("/error")
public ModelAndView handleError(HttpServletRequest request) {
String message = getErrorMessage(request);
if (message.startsWith("[access_denied]")) {
return new ModelAndView("access-denied");
public String handleError(Model model, HttpServletRequest request) {
String errorMessage = getErrorMessage(request);
if (errorMessage.startsWith("[access_denied]")) {
model.addAttribute("errorTitle", "Access Denied");
model.addAttribute("errorMessage", "You have denied access.");
} else {
model.addAttribute("errorTitle", "Error");
model.addAttribute("errorMessage", errorMessage);
}
return new ModelAndView("error", Map.of("message", message));
return "error";
}
private String getErrorMessage(HttpServletRequest request) {

6
samples/demo-authorizationserver/src/main/java/sample/web/DeviceController.java

@ -31,17 +31,17 @@ public class DeviceController { @@ -31,17 +31,17 @@ public class DeviceController {
if (userCode != null) {
return "redirect:/oauth2/device_verification?user_code=" + userCode;
}
return "activate";
return "device-activate";
}
@GetMapping("/activated")
public String activated() {
return "activated";
return "device-activated";
}
@GetMapping(value = "/", params = "success")
public String success() {
return "activated";
return "device-activated";
}
}

32
samples/demo-authorizationserver/src/main/resources/static/assets/css/signin.css

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
html,
body {
height: 100%;
}
body {
display: flex;
align-items: start;
padding-top: 100px;
background-color: #f5f5f5;
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="username"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}

13
samples/demo-authorizationserver/src/main/resources/static/assets/css/style.css

@ -1,13 +0,0 @@ @@ -1,13 +0,0 @@
html, body, .container, .jumbotron {
height: 100%;
}
.jumbotron {
margin-bottom: 0;
}
.gap {
margin-top: 70px;
}
.code {
font-size: 2em;
letter-spacing: 2rem;
}

BIN
samples/demo-authorizationserver/src/main/resources/static/assets/img/devices.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
samples/demo-authorizationserver/src/main/resources/static/assets/img/github.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
samples/demo-authorizationserver/src/main/resources/static/assets/img/google.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

20
samples/demo-authorizationserver/src/main/resources/templates/access-denied.html

@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Spring Security Example</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8">
<h2>Access Denied</h2>
<p>You have denied access.</p>
</div>
</div>
</div>
</body>
</html>

33
samples/demo-authorizationserver/src/main/resources/templates/activate.html

@ -1,33 +0,0 @@ @@ -1,33 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Device Grant Example</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
</head>
<body>
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-8">
<form th:action="@{/oauth2/device_verification}" method="post">
<h2>Device Activation</h2>
<p>Enter the activation code to authorize the device.</p>
<p class="gap">Activation Code</p>
<div class="form-group">
<label class="sr-only" for="user_code">Activation Code</label>
<input type="text" class="form-control" id="user_code" name="user_code" placeholder="Activation Code" autofocus>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<div class="col-md-4">
<img src="https://cdn.pixabay.com/photo/2017/07/03/15/20/technology-2468063_1280.png" class="img-responsive" alt="Devices">
</div>
</div>
</div>
</div>
</body>
</html>

25
samples/demo-authorizationserver/src/main/resources/templates/activated.html

@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Device Grant Example</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
</head>
<body>
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-8">
<h2>Success!</h2>
<p>You have successfully activated your device. Please return to your device to continue.</p>
</div>
<div class="col-md-4">
<img src="https://cdn.pixabay.com/photo/2017/07/03/15/20/technology-2468063_1280.png" class="img-responsive" alt="Devices">
</div>
</div>
</div>
</div>
</body>
</html>

62
samples/demo-authorizationserver/src/main/resources/templates/consent.html

@ -1,44 +1,48 @@ @@ -1,44 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Custom consent page - Consent required</title>
<script>
function cancelConsent() {
document.consent_form.reset();
document.consent_form.submit();
}
</script>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<script>
function cancelConsent() {
document.consent_form.reset();
document.consent_form.submit();
}
</script>
</head>
<body>
<div class="container">
<div class="py-5">
<div class="row py-5">
<h1 class="text-center text-primary">App permissions</h1>
</div>
<div class="row">
<div class="col text-center">
<p>
The application
<span class="font-weight-bold text-primary" th:text="${clientId}"></span>
<span class="fw-bold text-primary" th:text="${clientId}"></span>
wants to access your account
<span class="font-weight-bold" th:text="${principalName}"></span>
<span class="fw-bold" th:text="${principalName}"></span>
</p>
</div>
</div>
<div th:if="${userCode}" class="row">
<div class="col text-center">
<p class="alert alert-warning">You have provided the code
<span class="font-weight-bold" th:text="${userCode}"></span>.
<p class="alert alert-warning">
You have provided the code
<span class="fw-bold" th:text="${userCode}"></span>.
Verify that this code matches what is shown on your device.
</p>
</div>
</div>
<div class="row pb-3">
<div class="col text-center"><p>The following permissions are requested by the above app.<br/>Please review
these and consent if you approve.</p></div>
<div class="col text-center">
<p>
The following permissions are requested by the above app.<br/>
Please review these and consent if you approve.
</p>
</div>
</div>
<div class="row">
<div class="col text-center">
@ -47,33 +51,37 @@ @@ -47,33 +51,37 @@
<input type="hidden" name="state" th:value="${state}">
<input th:if="${userCode}" type="hidden" name="user_code" th:value="${userCode}">
<div th:each="scope: ${scopes}" class="form-group form-check py-1">
<div th:each="scope: ${scopes}" class="form-check py-1">
<input class="form-check-input"
style="float: none"
type="checkbox"
name="scope"
th:value="${scope.scope}"
th:id="${scope.scope}">
<label class="form-check-label font-weight-bold" th:for="${scope.scope}" th:text="${scope.scope}"></label>
<label class="form-check-label fw-bold px-2" th:for="${scope.scope}" th:text="${scope.scope}"></label>
<p class="text-primary" th:text="${scope.description}"></p>
</div>
<p th:if="${not #lists.isEmpty(previouslyApprovedScopes)}">You have already granted the following permissions to the above app:</p>
<div th:each="scope: ${previouslyApprovedScopes}" class="form-group form-check py-1">
<p th:if="${not #lists.isEmpty(previouslyApprovedScopes)}">
You have already granted the following permissions to the above app:
</p>
<div th:each="scope: ${previouslyApprovedScopes}" class="form-check py-1">
<input class="form-check-input"
style="float: none"
type="checkbox"
th:id="${scope.scope}"
disabled
checked>
<label class="form-check-label font-weight-bold" th:for="${scope.scope}" th:text="${scope.scope}"></label>
<label class="form-check-label fw-bold px-2" th:for="${scope.scope}" th:text="${scope.scope}"></label>
<p class="text-primary" th:text="${scope.description}"></p>
</div>
<div class="form-group pt-3">
<div class="pt-3">
<button class="btn btn-primary btn-lg" type="submit" id="submit-consent">
Submit Consent
</button>
</div>
<div class="form-group">
<div class="pt-3">
<button class="btn btn-link regular" type="button" id="cancel-consent" onclick="cancelConsent();">
Cancel
</button>
@ -85,8 +93,8 @@ @@ -85,8 +93,8 @@
<div class="col text-center">
<p>
<small>
Your consent to provide access is required.
<br/>If you do not approve, click Cancel, in which case no information will be shared with the app.
Your consent to provide access is required.<br/>
If you do not approve, click Cancel, in which case no information will be shared with the app.
</small>
</p>
</div>

33
samples/demo-authorizationserver/src/main/resources/templates/device-activate.html

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spring Authorization Server sample</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
</head>
<body>
<div class="container">
<div class="row py-5">
<div class="col-md-5">
<h2>Device Activation</h2>
<p>Enter the activation code to authorize the device.</p>
<div class="mt-5">
<form th:action="@{/oauth2/device_verification}" method="post">
<div class="mb-3">
<label for="user_code" class="form-label">Activation Code</label>
<input type="text" id="user_code" name="user_code" class="form-control" required autofocus>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
<div class="col-md-7">
<img src="/assets/img/devices.png" th:src="@{/assets/img/devices.png}" class="img-responsive" alt="Devices">
</div>
</div>
</div>
</body>
</html>

25
samples/demo-authorizationserver/src/main/resources/templates/device-activated.html

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spring Authorization Server sample</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
</head>
<body>
<div class="container">
<div class="row py-5">
<div class="col-md-5">
<h2 class="text-success">Success!</h2>
<p>
You have successfully activated your device.<br/>
Please return to your device to continue.
</p>
</div>
<div class="col-md-7">
<img src="/assets/img/devices.png" th:src="@{/assets/img/devices.png}" class="img-responsive" alt="Devices">
</div>
</div>
</div>
</body>
</html>

31
samples/demo-authorizationserver/src/main/resources/templates/error.html

@ -1,20 +1,19 @@ @@ -1,20 +1,19 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Spring Security Example</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8">
<h2>Error</h2>
<p th:text="${message}"></p>
</div>
</div>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spring Authorization Server sample</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
</head>
<body>
<div class="container">
<div class="row py-5">
<div class="col-md-6">
<h2 class="text-danger" th:text="${errorTitle}"></h2>
<p th:text="${errorMessage}"></p>
</div>
</body>
</div>
</div>
</body>
</html>

55
samples/demo-authorizationserver/src/main/resources/templates/login.html

@ -1,41 +1,42 @@ @@ -1,41 +1,42 @@
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Spring Security Example</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spring Authorization Server sample</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
<link rel="stylesheet" href="/assets/css/signin.css" th:href="@{/assets/css/signin.css}" />
</head>
<body>
<div class="container">
<form class="form-signin" method="post" th:action="@{/login}">
<form class="form-signin w-100 m-auto" method="post" th:action="@{/login}">
<div th:if="${param.error}" class="alert alert-danger" role="alert">
Invalid username or password.
</div>
<div th:if="${param.logout}" class="alert alert-success" role="alert">
You have been logged out.
</div>
<h2 class="form-signin-heading">Sign In</h2>
<p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<a class="btn btn-light btn-block bg-white" href="/oauth2/authorization/google-idp" role="link" style="text-transform: none;">
<img width="20" style="margin-right: 5px;" alt="Sign in with Google" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/512px-Google_%22G%22_Logo.svg.png" />
Sign in with Google
</a>
<a class="btn btn-light btn-block bg-white" href="/oauth2/authorization/github-idp" role="link" style="text-transform: none;">
<img width="24" style="margin-right: 5px;" alt="Sign in with GitHub" src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" />
Sign in with Github
</a>
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input type="text" id="username" name="username" class="form-control" required autofocus>
<label for="username">Username</label>
</div>
<div class="form-floating">
<input type="password" id="password" name="password" class="form-control" required>
<label for="password">Password</label>
</div>
<div>
<button class="w-100 btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<a class="w-100 btn btn-light btn-block bg-white" href="/oauth2/authorization/google-idp" role="link" style="margin-top: 10px">
<img src="/assets/img/google.png" th:src="@{/assets/img/google.png}" width="20" style="margin-right: 5px;" alt="Sign in with Google">
Sign in with Google
</a>
<a class="w-100 btn btn-light btn-block bg-white" href="/oauth2/authorization/github-idp" role="link" style="margin-top: 10px">
<img src="/assets/img/github.png" th:src="@{/assets/img/github.png}" width="24" style="margin-right: 5px;" alt="Sign in with Github">
Sign in with Github
</a>
</div>
</form>
</div>
</body>
</html>
</html>

Loading…
Cancel
Save