{"id":93010,"date":"2019-06-17T19:22:51","date_gmt":"2019-06-17T16:22:51","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=93010"},"modified":"2019-06-24T10:54:44","modified_gmt":"2019-06-24T07:54:44","slug":"quick-guide-spring-boot-options","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/06\/quick-guide-spring-boot-options.html","title":{"rendered":"A Quick Guide to Spring Boot Login Options"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"http:\/\/bit.ly\/2KnZFqr\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n<p>In this post, you\u2019re going to work through various options for implementing a login feature using Spring Boot 2.1. You\u2019ll start with the most simple, basic auth, which you\u2019d likely never want to use except for perhaps an internal backend tool, and move on to a simple form-based authentication page. Next, you\u2019ll customize the default, auto-generated form by overriding some default templates and controllers. Finally, you\u2019ll move on to adding Single Sign-on using OAuth 2.0. You\u2019ll see how to allow the user to sign in using Github and Okta.<\/p>\n<p>The assumptions for this tutorial are pretty basic. I\u2019m assuming that you\u2019ve got a basic familiarity with Spring and Spring Boot, but not necessarily an in-depth understanding of Spring Security or Spring\u2019s various security features. You\u2019ll want to have&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">git<\/code>installed, and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">gradle<\/code>&nbsp;would be nice, but you can use the Gradle wrapper for all of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">gradle<\/code>&nbsp;commands, so that\u2019s not strictly necessary.<\/p>\n<p>Go ahead and clone the\u00a0<a href=\"http:\/\/bit.ly\/2KZtFbV\">the repository<\/a>\u00a0I created for this tutorial:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">git clone https:\/\/github.com\/oktadeveloper\/okta-spring-boot-login-options-example.git<\/pre>\n<p>This repository contains five subdirectories:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">basic-auth<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">form-auth<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">custom-form-auth<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-start<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-okta-github<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-okta-starter<\/code><\/li>\n<\/ul>\n<p>These correspond to the four sections of this tutorial (with three for the last section, the OAuth section). Except for the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-start<\/code>, these are fully functional applications. In this tutorial, you\u2019ll walk through what the code means and how to build them.<\/p>\n<h2 class=\"wp-block-heading\" id=\"build-http-basic-login-in-spring-boot\">Build HTTP Basic Login in Spring Boot<\/h2>\n<p>Basic authentication is, well, basic. It\u2019s a simple scheme built directly into the HTTP protocol. It comes from pastoral times before massive amounts of data and money flowed through the various pipes and tubes of the internet. As such, it\u2019s really not incredibly secure. According to the spec, the password and username are encoded using Base64 in the HTTP&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">authorization<\/code>&nbsp;header. Because Base64 might as well be plain text, if you are going to use basic auth for anything, make sure that you\u2019re always using HTTPS\/SSL because you\u2019re sending your authentication credentials with every request.<\/p>\n<p>Open the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">basic-auth<\/code>&nbsp;Spring Boot project with your favorite IDE or editor.<\/p>\n<p>The first thing you\u2019ll want to check out is the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file. It\u2019s reproduced below. I won\u2019t go through all of them in detail but I want to orient you to a few things going on here in case you\u2019re not already familiar.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">plugins {  \n    id 'org.springframework.boot' version '2.1.4.RELEASE'  \n    id 'java'  \n}  \n  \napply plugin: 'io.spring.dependency-management'  \n\ngroup = 'com.okta.springsecurityauth'  \nversion = '0.0.1-SNAPSHOT'  \nsourceCompatibility = '1.8'  \n  \nrepositories {  \n    mavenCentral()  \n}  \n  \ndependencies {  \n    implementation 'org.springframework.boot:spring-boot-starter-security'  \n    implementation 'org.springframework.boot:spring-boot-starter-web'  \n    testImplementation 'org.springframework.boot:spring-boot-starter-test'  \n    testImplementation 'org.springframework.security:spring-security-test'  \n}\n<\/pre>\n<p>There are two Spring plugins being added to the build:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">org.springframework.boot<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">io.spring.dependency-management<\/code>. Notice that the version is set to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">2.1.4.RELEASE<\/code>. One of the real pains with Spring in the past has been dependency management. Spring is a huge collection of libraries, and when you bring in one, you need to bring in others with compatible versions. When you update one, often this causes others to fall out of compatibility. Fixing this in the past could land you in what was called \u201cdependency hell.\u201d<\/p>\n<p>Fortunately, Spring has made things much easier. Look at our two Spring dependencies:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">dependencies {  \n    implementation 'org.springframework.boot:spring-boot-starter-security'  \n    implementation 'org.springframework.boot:spring-boot-starter-web'  \n... \n}\n<\/pre>\n<p>Notice that they have no version numbers. These are basically large, meta-dependencies for feature sets (security and web, in this case), and the Spring plugins manage all of the sub-dependencies for you based on the version set in this line:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">id 'org.springframework.boot' version '2.1.4.RELEASE'<\/pre>\n<p>The executive summary of all that is that this&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file will be loading Spring Boot version 2.1.4 and will be adding the web and security feature modules. A list of all the available starters from Spring&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/htmlsingle\/#using-boot-starter\">can be found in their docs<\/a>.<\/p>\n<p>Other than the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">gradle.file<\/code>, there are really only three other files of interest, all Java files. Look under&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/java\/com\/okta\/springsecurityauth<\/code>&nbsp;and you\u2019ll see them:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Application.java<\/code>&nbsp;(the main class that auto-magic\u2019s the whole Spring Boot framework into existence)<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code>&nbsp;(configures the security options)<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">WebController.java<\/code>&nbsp;(a very basic HTTP request controller)<\/li>\n<\/ul>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Application.java<\/code>&nbsp;is the entry point into the app. It\u2019s pretty simple in this case, and in many cases. The most important thing is the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@SpringBootApplication<\/code>&nbsp;annotation, which tells your Spring dependencies to bootstrap the whole Spring Boot framework. There is, of course, also the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">main()<\/code>&nbsp;method, which is where the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Application<\/code>&nbsp;class is loaded and run by Spring.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springsecurityauth;  \n  \nimport org.springframework.boot.SpringApplication;  \nimport org.springframework.boot.autoconfigure.SpringBootApplication;  \n  \n@SpringBootApplication  \npublic class Application {  \n  \n    public static void main(String[] args) {  \n        SpringApplication.run(Application.class, args);  \n    }  \n  \n}\n<\/pre>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">WebController.java<\/code>&nbsp;is, cleverly enough, your web request controller. It defines request endpoints and determines the responses.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springsecurityauth;  \n  \nimport org.springframework.stereotype.Controller;  \nimport org.springframework.web.bind.annotation.RequestMapping;  \nimport org.springframework.web.bind.annotation.ResponseBody;  \n  \n@Controller  \npublic class WebController {  \n      \n    @RequestMapping(\"\/\")  \n    @ResponseBody  \n    public String index() {  \n        return \"That's pretty basic!\";  \n    }  \n  \n}\n<\/pre>\n<p>In this case, the web controller is returning a simple string instead of routing to a template file, as we\u2019ll see in a bit. The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@ResponseBody<\/code>&nbsp;annotation is what allows this method to directly return the string.<\/p>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code>&nbsp;is where the action is happening in this tutorial. This is where Spring Boot is configured to use basic authentication. This is also where you can configure a hard-coded default user and password (not something I\u2019d do in production, obviously, but great for tutorials).<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springsecurityauth;  \n  \nimport org.springframework.context.annotation.Configuration;  \nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  \nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;  \nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  \n  \n@Configuration  \npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {  \n      \n    @Override  \n    public void configure(HttpSecurity http) throws Exception {  \n        http  \n            .authorizeRequests()  \n            .anyRequest().authenticated()  \n            .and()  \n            .httpBasic();  \n    }  \n      \n    @Override  \n    protected void configure(AuthenticationManagerBuilder auth) throws Exception {  \n        auth.inMemoryAuthentication()  \n            .withUser(\"user\")  \n            .password(\"{noop}pass\") \/\/ Spring Security 5 requires specifying the password storage format  \n            .roles(\"USER\");  \n    }  \n      \n}\n<\/pre>\n<p>If you look at the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">configure()<\/code>&nbsp;method, you\u2019ll see the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http<\/code>&nbsp;object being used with its fluent interface to tell spring to authenticate all requests and use HTTP basic authentication. This is pretty trivial, but there\u2019s tons of power here in this interface as you\u2019ll see in a minute.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">configure()<\/code>&nbsp;method is mostly a hack for this tutorial to create a user in an in-memory authentication manager. You\u2019re creating a user with username&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">user<\/code>&nbsp;and password&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pass<\/code>. The user has the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">USER<\/code>&nbsp;role assigned to it.<\/p>\n<p>That\u2019s it!<\/p>\n<p>Open a terminal and make sure you\u2019re in the root directory of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">basic-auth<\/code>&nbsp;project. Run the project with the following command:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/gradlew bootRun<\/pre>\n<p>Wait for the Spring Boot app to finish loading.<\/p>\n<p>Navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>.<\/p>\n<p>You\u2019ll see a login window.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"610\" height=\"390\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/basic-auth.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93013\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/basic-auth.png 610w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/basic-auth-300x192.png 300w\" sizes=\"(max-width: 610px) 100vw, 610px\" \/><\/figure>\n<\/div>\n<p>Log in using&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">user<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pass<\/code>&nbsp;as credentials.<\/p>\n<p>You\u2019ll be taken to a success screen that says, \u201cThat\u2019s pretty basic!\u201d<\/p>\n<h2 class=\"wp-block-heading\" id=\"configure-spring-boot-form-based-login\">Configure Spring Boot Form-based Login<\/h2>\n<p>When using basic auth, the login form is actually generated by the browser, not by the application. It appears as an un-styled pop-up window. This isn\u2019t great flow or very professional looking.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>With some pretty minimal changes to the code, you can have Spring Boot auto-generate a more professional-looking login form. The completed code can be found in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">form-auth<\/code>&nbsp;subdirectory of the GitHub repo, or you can just make the changes to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">basic-auth<\/code>&nbsp;project if that\u2019s still open.<\/p>\n<p>You want to change the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">configure()<\/code>&nbsp;method of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code>&nbsp;file to look like this:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">@Override  \npublic void configure(HttpSecurity http) throws Exception {  \n    http  \n        .authorizeRequests()  \n        .anyRequest().authenticated()  \n        .and()  \n        .formLogin()  \n        .and()  \n        .httpBasic();  \n}\n<\/pre>\n<p>The only different is the addition of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.and().formLogin()<\/code>. Other than that the two projects are the same.<\/p>\n<p>Run it again using&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code>.<\/p>\n<p>Navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>&nbsp;(you may need to open an incognito window to trigger re-authentication).<\/p>\n<p>This time you\u2019ll see the login page that Spring generates for you.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"507\" height=\"366\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/form-login.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93014\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/form-login.png 507w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/form-login-300x217.png 300w\" sizes=\"(max-width: 507px) 100vw, 507px\" \/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"customize-the-spring-boot-login-form\">Customize the Spring Boot Login Form<\/h2>\n<p>The next step in our journey of increasingly sophisticated Spring Boot authentication is to customize the login form. Spring makes this super easy. There are, however, a number of new files and more changes to the code than last time, so I\u2019d suggest opening the project found under the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">custom-form-auth<\/code>&nbsp;folder of the repo.<\/p>\n<p>In the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file there\u2019s one new dependency. This brings in the Thymeleaf templating engine, the default web templating engine for use with Spring Boot.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">dependencies {  \n    ...\n    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  \n    ... \n}\n<\/pre>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code>&nbsp;file now looks like this (with some parts omitted for brevity):<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springsecurityauth;  \n  \n...\n  \n@Configuration  \n@EnableWebSecurity  \npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {  \n      \n    @Override  \n    public void configure(HttpSecurity http) throws Exception {  \n        http  \n            .authorizeRequests()  \n            .antMatchers( \"\/public\/**\").permitAll()  \n            .anyRequest().authenticated()  \n                .and()  \n            .formLogin()  \n                .loginPage(\"\/login.html\")  \n                .failureUrl(\"\/login-error.html\")  \n                .permitAll();  \n    }\n\n    ...\n\n}\n<\/pre>\n<p>Notice that the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.httpBasic()<\/code>&nbsp;is gone, and the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.formLogin()<\/code>&nbsp;has some new options. Here you\u2019re setting a login page and a login failure page and making sure that these are publicly available.<\/p>\n<p>Also notice this line:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.antMatchers( \"\/public\/**\").permitAll()<\/pre>\n<p>Here you are making the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">public<\/code>&nbsp;directory on the classpath root available without authentication. Under&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/static<\/code>&nbsp;there is a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">public<\/code>&nbsp;directory. When the app is launched, everything under the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/static<\/code>&nbsp;directory is copied to the classpath, so the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">public<\/code>&nbsp;directory ends up at the classpath root and all files within it will be available without authentication. This is great for things like images, JavaScript files, and CSS files.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">WebController.java<\/code>&nbsp;also has some new endpoints:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springsecurityauth;  \n  \n...\n  \n@Controller  \npublic class WebController {  \n      \n    @RequestMapping(\"\/\")  \n    @ResponseBody  \n    public String index() {  \n        return \"You made it!\";  \n    }  \n\n    \/\/ Login form  \n    @RequestMapping(\"\/login.html\")  \n    public String login() {  \n        return \"login.html\";  \n    }  \n\n    \/\/ Login form with error  \n    @RequestMapping(\"\/login-error.html\")  \n    public String loginError(Model model) {  \n        model.addAttribute(\"loginError\", true);  \n        return \"login.html\";  \n    }  \n\n}\n<\/pre>\n<p>Notice that while the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">index()<\/code>&nbsp;method has the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@RequestBody<\/code>&nbsp;annotation, meaning that it is going to return its request body directly as a string, the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">login()<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">loginError()<\/code>&nbsp;methods do not. Instead, they are returning the name of the Thymeleaf templates that Spring Boot will render. By default these templates are found under&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates<\/code>. Also, notice that the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">loginError()<\/code>&nbsp;is a bit of a routing trick. It actually just returns the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">login.html<\/code>&nbsp;template but with an error attribute injected into the model.<\/p>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates\/login.html<\/code>&nbsp;is a new file. It\u2019s the login template file.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;!DOCTYPE html&gt;  \n&lt;html xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;  \n&lt;head&gt;  \n    &lt;title&gt;Login page&lt;\/title&gt;  \n    &lt;link th:href=\"@{\/public\/style.css}\" rel=\"stylesheet\" \/&gt;  \n&lt;\/head&gt;  \n&lt;body&gt;  \n&lt;div id=\"container\"&gt;  \n    &lt;h2&gt;Login page&lt;\/h2&gt;  \n    &lt;form th:action=\"@{\/login.html}\" method=\"post\"&gt;  \n        &lt;label for=\"username\"&gt;Username&lt;\/label&gt;  \n        &lt;input type=\"text\" id=\"username\" name=\"username\" autofocus=\"autofocus\" \/&gt;  \n        &lt;label for=\"password\"&gt;Password&lt;\/label&gt;  \n        &lt;input type=\"password\" id=\"password\" name=\"password\" \/&gt;  \n        &lt;input id=\"submit\" type=\"submit\" value=\"Log in\" \/&gt;  \n    &lt;\/form&gt;  \n    &lt;p th:if=\"${loginError}\" class=\"error\"&gt;Wrong user or password&lt;\/p&gt;  \n&lt;\/div&gt;  \n&lt;\/body&gt;  \n&lt;\/html&gt;\n<\/pre>\n<p>A real, in-depth explanation of Thymeleaf is well beyond the scope of this tutorial. Head over to&nbsp;<a href=\"https:\/\/www.thymeleaf.org\/index.html\">their website<\/a>&nbsp;to dig into it if you like.<\/p>\n<p>Remember when you made the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">public<\/code>&nbsp;directory public? There is a very basic stylesheet that is being pulled in by this line here. Mostly I included this to demonstrate one way to include static resources in template files.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;link th:href=\"@{\/public\/style.css}\" rel=\"stylesheet\" \/&gt;<\/pre>\n<p>The error line is rendered conditionally based on the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">loginError<\/code>&nbsp;attribute of the model, which is injected by the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">loginError()<\/code>&nbsp;method of the controller.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;p th:if=\"${loginError}\" class=\"error\"&gt;Wrong user or password&lt;\/p&gt;\n<\/pre>\n<p>Other than that, it\u2019s a pretty simple login form!<\/p>\n<p>Once again,&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code>&nbsp;to run it.<\/p>\n<p>You\u2019ll see the styled, customized login form:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"664\" height=\"489\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/custom-login-form.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93015\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/custom-login-form.png 664w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/custom-login-form-300x221.png 300w\" sizes=\"(max-width: 664px) 100vw, 664px\" \/><\/figure>\n<\/div>\n<p>Log in again using&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">user:pass<\/code>&nbsp;and you\u2019ll see our success screen saying, \u201cYou made it!\u201d<\/p>\n<h2 class=\"wp-block-heading\" id=\"spring-boot-oauth-20-login-using-github-and-single-sign-on\">Spring Boot OAuth 2.0 Login Using GitHub and Single Sign-On<\/h2>\n<p>Up until this point, all of your authentications have been done locally, using the ad hoc in-memory&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">AuthenticationManager<\/code>. More commonly in production, applications are supporting OAuth 2.0 and OIDC (Open ID Connect). OAuth 2.0 is an open standard for authorization. OIDC is built on top of OAuth 2.0 and adds authentication, for a more complete identity management protocol.<\/p>\n<p>In this tutorial, you\u2019ll first see how to add Single Sign-on (SSO) using GitHub. After that, you\u2019ll see how to use Okta, a software-as-service identity solutions provider.<\/p>\n<p>Both are super easy, and there is a real benefit in allowing users to re-use existing identity providers. Forcing users to handle and manage separate, strong passwords for hundreds of websites is a fool\u2019s errand that ultimately results in weaker passwords and passwords reused across multiple sites (multiplying their vulnerability to attack); not to mention the old \u201cjust scribble it on a sticky note and stick it to the monitor\u201d password management solution.<\/p>\n<h2 class=\"wp-block-heading\" id=\"simplify-your-spring-boot-app-login-with-github-single-sign-on\">Simplify Your Spring Boot App Login with GitHub Single Sign-on<\/h2>\n<p>Now it\u2019s time to implement a GitHub OAuth 2.0 client.<\/p>\n<p>First, you need to register a new OAuth application with GitHub. Go to&nbsp;<a href=\"https:\/\/github.com\/settings\/applications\/new\">their website<\/a>&nbsp;and do this now. Fill in the values as shown below.<\/p>\n<p>Pay particular attention to the&nbsp;<strong>Authorization callback URL<\/strong>, as this needs to be&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080\/login\/oauth2\/code\/github<\/code>.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"620\" height=\"577\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-registration.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93016\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-registration.png 620w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-registration-300x279.png 300w\" sizes=\"(max-width: 620px) 100vw, 620px\" \/><\/figure>\n<\/div>\n<p>Click&nbsp;<strong>Register application<\/strong>. Take note of the&nbsp;<strong>Client ID<\/strong>&nbsp;and&nbsp;<strong>Client Secret<\/strong>&nbsp;as you\u2019ll need them in a sec.<\/p>\n<p>Now, back to Java. Open the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-start<\/code>&nbsp;project in your IDE.<\/p>\n<p>In the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file, notice a couple of new dependencies:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">...\ndependencies {  \n    implementation 'org.springframework.boot:spring-boot-starter-security'  \n    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  \n    implementation 'org.springframework.boot:spring-boot-starter-web'  \n    implementation 'org.springframework.security:spring-security-oauth2-client'  \n    implementation 'org.springframework.security:spring-security-oauth2-jose'  \n    ...  \n}\n<\/pre>\n<p>The security, Thymeleaf, and web starters are still there. However, there two new Spring starters:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth2-client<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth2-jose<\/code>.<\/p>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth2-client<\/code>&nbsp;brings in the libraries required for implementing an OAuth 2.0 client.&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth2-jose<\/code>&nbsp;brings in some common libraries for signing and encryption. JOSE stands for Java Object Signing and Encryption.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code>&nbsp;file has been updated for OAuth login:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.spring.SpringBootOAuth;    \n...\n  \n@Configuration  \npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {  \n    @Override  \n    public void configure(HttpSecurity http) throws Exception {  \n        http.antMatcher(\"\/**\")  \n            .authorizeRequests()  \n            .antMatchers(\"\/\", \"\/login**\").permitAll()  \n            .anyRequest().authenticated()  \n            .and()  \n            .oauth2Login();  \n    }  \n}\n<\/pre>\n<p>Two things to notice: 1) all requests to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">login<\/code>&nbsp;are public, and 2) the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth2Login()<\/code>&nbsp;method is what is causing Spring Boot to configure the OAuth 2.0 client.<\/p>\n<p>If this seems&nbsp;<em>too easy<\/em>, you\u2019re correct. Some of the configuration has been moved to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml<\/code>&nbsp;file.<\/p>\n<p>Open the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/application.yml<\/code>&nbsp;file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">spring:  \n  thymeleaf:  \n    cache: false  \n  security:  \n    oauth2:  \n      client:  \n        registration:  \n          github:  \n            client-id: &lt;&lt; your GitHub client ID&gt;&gt;  \n            client-secret: &lt;&lt; your GitHub client secret &gt;&gt; \n<\/pre>\n<p>You need to fill in the&nbsp;<strong>Client ID<\/strong>&nbsp;and&nbsp;<strong>Client Secret<\/strong>&nbsp;from above into this file.<\/p>\n<p>The web routing and templating have changed as well. Look at the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">WebController.java<\/code>&nbsp;file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.spring.SpringBootOAuth;  \n\n...\n\n@Controller  \npublic class WebController {  \n\n    @RequestMapping(\"\/securedPage\")  \n    public String securedPage(Model model,  \n                              @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,  \n                              @AuthenticationPrincipal OAuth2User oauth2User) {  \n        model.addAttribute(\"userName\", oauth2User.getName());  \n        model.addAttribute(\"clientName\", authorizedClient.getClientRegistration().getClientName());  \n        model.addAttribute(\"userAttributes\", oauth2User.getAttributes());  \n        return \"securedPage\";  \n    }  \n  \n    @RequestMapping(\"\/\")  \n    public String index() {  \n        return \"index\";  \n    }  \n  \n}\n<\/pre>\n<p>This controller defines two endpoints that return two template files:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/<\/code>&nbsp;\u2013&gt;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates\/index.html<\/code><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/securedPage<\/code>&nbsp;\u2013&gt;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates\/securedPage.html<\/code><\/li>\n<\/ul>\n<p>In the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">securedPage()<\/code>&nbsp;method, notice how dependency injection is used to get information about the authenticated user so that it can be injected into the model, which is then passed to the template file.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates\/index.html<\/code>&nbsp;is pretty simple:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;!DOCTYPE html&gt;  \n&lt;html lang=\"en\"&gt;  \n&lt;head&gt;  \n    &lt;meta charset=\"UTF-8\"&gt;  \n    &lt;title&gt;Home&lt;\/title&gt;  \n&lt;\/head&gt;  \n&lt;body&gt;  \n    &lt;h1&gt;Spring Security SSO&lt;\/h1&gt;  \n    &lt;a href=\"securedPage\"&gt;Login&lt;\/a&gt;  \n&lt;\/body&gt;  \n&lt;\/html&gt; \n<\/pre>\n<p>And the&nbsp;<code>src\/main\/resources\/templates\/securedPage.html<\/code>&nbsp;template file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;!DOCTYPE html&gt;  \n&lt;html xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;  \n&lt;head&gt;  \n    &lt;meta charset=\"UTF-8\"&gt;  \n    &lt;title&gt;Secured Page&lt;\/title&gt;  \n&lt;\/head&gt;  \n&lt;body&gt;  \n    &lt;h1&gt;Secured Page&lt;\/h1&gt;  \n    &lt;div&gt;User Name: &lt;span th:text=\"${userName}\"&gt;&lt;\/span&gt;&lt;\/div&gt;  \n    &lt;div&gt;Client Name: &lt;span th:text=\"${clientName}\"&gt;&lt;\/span&gt;&lt;\/div&gt;  \n    &lt;div&gt;User Attributes: &lt;span th:text=\"${userAttributes}\"&gt;&lt;\/span&gt;&lt;\/div&gt;  \n&lt;\/body&gt;  \n&lt;\/html&gt;\n<\/pre>\n<p>Now you\u2019re ready to try it out. Again, make sure you\u2019re in the project root, and run&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code>.<\/p>\n<p>Navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>&nbsp;and click the&nbsp;<strong>Login<\/strong>&nbsp;link.<\/p>\n<p>If your browser bypasses the login page and goes straight to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/securedPage<\/code>&nbsp;endpoint, open an incognito browser and try it again.<\/p>\n<p>First, you will need to authorize the Spring Boot Login application to use your Github account for OAuth login.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"662\" height=\"681\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-authorize.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93017\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-authorize.png 662w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-authorize-292x300.png 292w\" sizes=\"(max-width: 662px) 100vw, 662px\" \/><\/figure>\n<\/div>\n<p>Next, you will see the GitHub OAuth login screen:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"464\" height=\"692\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-login.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93018\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-login.png 464w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/github-login-201x300.png 201w\" sizes=\"(max-width: 464px) 100vw, 464px\" \/><\/figure>\n<\/div>\n<p>If you\u2019re successful, you\u2019ll see a simple text page that says \u201cSecured Page\u201d in bold letters and displays some information about your OAuth user.<\/p>\n<p>Pretty sweet, huh?<\/p>\n<p>Now you\u2019re going to add a second OAuth provider: Okta.<\/p>\n<h2 class=\"wp-block-heading\" id=\"add-oauth-20-login-with-okta-to-your-spring-boot-app\">Add OAuth 2.0 Login with Okta to Your Spring Boot App<\/h2>\n<p>First, go to&nbsp;<a href=\"http:\/\/bit.ly\/2Knr7Vx\">developer.okta.com<\/a>&nbsp;and sign up for a free developer account, if you don\u2019t already have one.<\/p>\n<p>Once you have an account, to create an OAuth\/OIDC app, open your Okta developer dashboard. Click on the&nbsp;<strong>Applications<\/strong>&nbsp;top menu item, and then click on&nbsp;<strong>Add Application<\/strong>.<\/p>\n<p>Select&nbsp;<strong>Web<\/strong>&nbsp;as the platform and click&nbsp;<strong>Next<\/strong>.<\/p>\n<p>Give the app a name. I named mine \u201cSpring Boot Login\u201d, but you can name yours whatever you like.<\/p>\n<p>Change the&nbsp;<strong>Login redirect URIs<\/strong>&nbsp;to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080\/login\/oauth2\/code\/okta<\/code>.<\/p>\n<p>The other defaults are fine.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"696\" height=\"847\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/oidc-settings.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93019\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/oidc-settings.png 696w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/oidc-settings-247x300.png 247w\" sizes=\"(max-width: 696px) 100vw, 696px\" \/><\/figure>\n<\/div>\n<p>Click&nbsp;<strong>Done<\/strong>.<\/p>\n<p>Take note of the&nbsp;<strong>Client ID<\/strong>&nbsp;and&nbsp;<strong>Client Secret<\/strong>&nbsp;on the next page.<\/p>\n<p>Update the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml<\/code>&nbsp;file for Okta:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">spring:  \n  ...\n  security:  \n    oauth2:  \n      client:  \n        registration:  \n          github:  \n            client-id: &lt;&lt; Your GitHub Client ID &gt;&gt;  \n            client-secret: &lt;&lt; Your GitHub Client Secret &gt;&gt;  \n          okta:  \n            client-id: &lt;&lt; Your Okta Client ID &gt;&gt;  \n            client-secret: &lt;&lt; Your Okta Client Secret &gt;&gt; \n            client-name: Okta\n        provider:  \n          okta:  \n            issuer-uri: https:\/\/{yourOktaDomain}\/oauth2\/default\n<\/pre>\n<p>You need to add the Okta registration and provider entries, making sure to fill in your&nbsp;<strong>Client ID<\/strong>,&nbsp;<strong>Client Secret<\/strong>, and Okta issuer.<\/p>\n<p>Restart the app, go to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>, and click the&nbsp;<strong>Login<\/strong>&nbsp;link.<\/p>\n<p>This time you\u2019ll be given a choice of OAuth providers. This screen is auto-generated by Spring Boot.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"517\" height=\"262\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/spring-security-oauth-login.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93020\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/spring-security-oauth-login.png 517w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/spring-security-oauth-login-300x152.png 300w\" sizes=\"(max-width: 517px) 100vw, 517px\" \/><\/figure>\n<\/div>\n<p>Click&nbsp;<strong>Okta<\/strong>&nbsp;and you\u2019ll be taken to the Okta login page (usual caveat about logging out and\/or incognito apply).<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"549\" height=\"644\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93021\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login.png 549w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-256x300.png 256w\" sizes=\"(max-width: 549px) 100vw, 549px\" \/><\/figure>\n<\/div>\n<p>Log in successfully and you\u2019ll see our success page.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"504\" height=\"267\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/secured-page-success-.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93022\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/secured-page-success-.png 504w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/secured-page-success--300x160.png 300w\" sizes=\"(max-width: 504px) 100vw, 504px\" \/><\/figure>\n<\/div>\n<p>At this point, you\u2019ve brought the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-start<\/code>&nbsp;project up to date with the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-github-okta<\/code>&nbsp;project folder, and you\u2019ve seen how easy it is to add multiple OAuth providers to a Spring Boot app.<\/p>\n<h2 class=\"wp-block-heading\" id=\"simplify-oauth-20-login-with-oktas-spring-boot-starter\">Simplify OAuth 2.0 Login With Okta\u2019s Spring Boot Starter<\/h2>\n<p>The last thing you\u2019re going to do in this tutorial is to configure Okta to allow new user registration. Before you do that, however, I want to introduce you to the Okta Spring Boot Starter. The project simplifies integrating Spring Boot and Okta.&nbsp;<a href=\"https:\/\/github.com\/okta\/okta-spring-boot\/blob\/master\/README.md\">The project\u2019s README<\/a>&nbsp;is a great source for more in-depth info.<\/p>\n<p>You\u2019re going to integrate the Okta Spring Boot Starter into this project and simplify the configuration a little. Just for simplicity, you\u2019re also going to remove the GitHub OAuth integration.<\/p>\n<p>Add one dependency to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">dependencies {\n    ...\n    implementation 'com.okta.spring:okta-spring-boot-starter:1.1.0'\n    ...\n}\n<\/pre>\n<p>Now update the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml<\/code>&nbsp;file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">okta:  \n  oauth2:  \n    issuer: https:\/\/{yourOktaDomain}\/oauth2\/default  \n    client-id: &lt;&lt;yourOktaClientID&gt;&gt;\n    client-secret: &lt;&lt;yourOktaClientSecret&gt;&gt; \nspring:  \n  thymeleaf:  \n    cache: false\n<\/pre>\n<p>Fill in your&nbsp;<strong>Client Secret<\/strong>&nbsp;and&nbsp;<strong>Client ID<\/strong>.<\/p>\n<p>Try it. Run&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code>.<\/p>\n<p>You should be able to log in via Okta. This time you won\u2019t be given a choice of OAuth 2.0 providers.<\/p>\n<h2 class=\"wp-block-heading\" id=\"enable-user-registration\">Enable User Registration<\/h2>\n<p>Log into your&nbsp;<a href=\"http:\/\/bit.ly\/2Knr7Vx\">developer.okta.com<\/a>&nbsp;account.<\/p>\n<p>Hover over&nbsp;<strong>Users<\/strong>&nbsp;and click on&nbsp;<strong>Registration<\/strong>.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"684\" height=\"556\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/user-registration.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93023\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/user-registration.png 684w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/user-registration-300x244.png 300w\" sizes=\"(max-width: 684px) 100vw, 684px\" \/><\/figure>\n<\/div>\n<p>Enable registration. Also, enable the&nbsp;<strong>Show \u201cSign Up\u201d link in the sign-in page\u2026<\/strong>&nbsp;option. This causes the registration link to be shown in the hosted login page.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/enable-registration.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93024\" width=\"729\" height=\"693\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/enable-registration.png 972w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/enable-registration-300x285.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/enable-registration-768x730.png 768w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/figure>\n<\/div>\n<p>Log in again, using an incognito window. This time you\u2019ll notice the user has the option of registering as a new user.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"582\" height=\"773\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-with-signup.png\" alt=\"Spring Boot Login Options\" class=\"wp-image-93025\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-with-signup.png 582w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-with-signup-226x300.png 226w\" sizes=\"(max-width: 582px) 100vw, 582px\" \/><\/figure>\n<\/div>\n<p>Enter your email address, password, and name; set up a few security questions, and you\u2019re done! You registered a new user for your application using Okta.<\/p>\n<p>There\u2019s a lot more you can do with Okta\u2019s Self-Service Registration options. All of this can be configured and customized. Take a look at&nbsp;<a href=\"https:\/\/help.okta.com\/en\/prod\/Content\/Topics\/Directory\/eu-self-service.htm\">their docs<\/a>&nbsp;to dig deeper.<\/p>\n<p>The final product for this using the Okta Spring Boot Starter and with the GitHub OAuth removed is found in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">oauth-okta-starter<\/code>&nbsp;directory.<\/p>\n<h2 class=\"wp-block-heading\" id=\"learn-more-about-spring-boot-login-options-and-secure-authentication\">Learn More About Spring Boot Login Options and Secure Authentication<\/h2>\n<p>You covered a TON of territory in this tutorial. You implemented a Spring Boot app using basic auth, form-based auth, and customized form-based auth. You then used OAuth 2.0 and OIDC to implement SSO using GitHub and Okta. Finally, you saw how the Okta Spring Boot Starter can be used to simplify OAuth\/OIDC SSO configuration in Spring Boot, and how to allow users to self-service register with Okta.<\/p>\n<p>You can find all the code for the examples in this tutorial\u00a0<a href=\"http:\/\/bit.ly\/2KZtFbV\">on GitHub<\/a>.<\/p>\n<p>To dig deeper into creating custom login forms, take a look at&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/guides\/html5\/form-javaconfig.html\">the Spring documentation<\/a>&nbsp;on the subject.<\/p>\n<p>Spring Security\u2019s&nbsp;<a href=\"http:\/\/bit.ly\/2WRo1PW\">oauth2login sample<\/a>&nbsp;also has some great information and more examples.<\/p>\n<p>Here are some related blog posts that demonstrate how to use Spring Boot and Spring Security for login and authentication:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/10\/16\/token-auth-for-java\">Simple Token Authentication for Java Apps<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/09\/26\/build-a-spring-boot-webapp\">Build a Web App with Spring Boot and Spring Security in 15 Minutes<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/12\/18\/secure-spring-rest-api\">Create a Secure Spring REST API<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/11\/20\/build-crud-spring-and-vue\">Build a Simple CRUD App with Spring Boot and Vue.js<\/a><\/li>\n<\/ul>\n<p>If you enjoyed this post, follow us on social media {&nbsp;<a href=\"https:\/\/twitter.com\/oktadev\">Twitter<\/a>,&nbsp;<a href=\"https:\/\/www.facebook.com\/oktadevelopers\">Facebook<\/a>,&nbsp;<a href=\"https:\/\/www.linkedin.com\/company\/oktadev\/\">LinkedIn<\/a>,&nbsp;<a href=\"https:\/\/www.youtube.com\/channel\/UC5AMiWqFVFxF1q9Ya1FuZ_Q\">YouTube<\/a>&nbsp;} to know when we\u2019ve posted similar ones.<\/p>\n<p><a href=\"http:\/\/bit.ly\/2FbEWCb\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">&#8220;A Quick Guide to Spring Boot Login Options&#8221;<\/a>&nbsp;was originally published on the Okta developer blog on May 15, 2019.<\/p>\n<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"http:\/\/bit.ly\/2KnZFqr\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever. Tired of building the same login screens over and over? Try the Okta API for hosted authentication, authorization, and multi-factor auth. In this post, you\u2019re going to work through various options for implementing a login feature using Spring Boot 2.1. You\u2019ll start with &hellip;<\/p>\n","protected":false},"author":49514,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,854],"class_list":["post-93010","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A Quick Guide to Spring Boot Login Options - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A Quick Guide to Spring Boot Login Options - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-06-17T16:22:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-06-24T07:54:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrew Hughes\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Hughes\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/quick-guide-spring-boot-options.html\"},\"author\":{\"name\":\"Andrew Hughes\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0ded99ab51010abb68790f6189ce99d3\"},\"headline\":\"A Quick Guide to Spring Boot Login Options\",\"datePublished\":\"2019-06-17T16:22:51+00:00\",\"dateModified\":\"2019-06-24T07:54:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/quick-guide-spring-boot-options.html\"},\"wordCount\":3051,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/quick-guide-spring-boot-options.html\",\"url\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options\",\"name\":\"A Quick Guide to Spring Boot Login Options - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2019-06-17T16:22:51+00:00\",\"dateModified\":\"2019-06-24T07:54:44+00:00\",\"description\":\"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/15\\\/spring-boot-login-options#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"A Quick Guide to Spring Boot Login Options\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0ded99ab51010abb68790f6189ce99d3\",\"name\":\"Andrew Hughes\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"caption\":\"Andrew Hughes\"},\"sameAs\":[\"https:\\\/\\\/developer.okta.com\\\/blog\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrew-hughes\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A Quick Guide to Spring Boot Login Options - Java Code Geeks","description":"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options","og_locale":"en_US","og_type":"article","og_title":"A Quick Guide to Spring Boot Login Options - Java Code Geeks","og_description":"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1","og_url":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-06-17T16:22:51+00:00","article_modified_time":"2019-06-24T07:54:44+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Andrew Hughes","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrew Hughes","Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/quick-guide-spring-boot-options.html"},"author":{"name":"Andrew Hughes","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0ded99ab51010abb68790f6189ce99d3"},"headline":"A Quick Guide to Spring Boot Login Options","datePublished":"2019-06-17T16:22:51+00:00","dateModified":"2019-06-24T07:54:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/quick-guide-spring-boot-options.html"},"wordCount":3051,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/quick-guide-spring-boot-options.html","url":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options","name":"A Quick Guide to Spring Boot Login Options - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#primaryimage"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2019-06-17T16:22:51+00:00","dateModified":"2019-06-24T07:54:44+00:00","description":"Interested to learn about Spring Boot Login Options? Check our article presenting various options for implementing a login feature using Spring Boot 2.1","breadcrumb":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"A Quick Guide to Spring Boot Login Options"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0ded99ab51010abb68790f6189ce99d3","name":"Andrew Hughes","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","caption":"Andrew Hughes"},"sameAs":["https:\/\/developer.okta.com\/blog"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrew-hughes"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/93010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/49514"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=93010"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/93010\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=93010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=93010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=93010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}