Update web ui design for demo-authorizationserver
Issue gh-1196
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
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) {
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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 @@
|
||||
<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 @@
|
||||
<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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user