{"id":70234,"date":"2017-11-06T19:40:28","date_gmt":"2017-11-06T17:40:28","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=70234"},"modified":"2017-11-14T09:53:49","modified_gmt":"2017-11-14T07:53:49","slug":"secure-java-app-spring-security-thymeleaf-okta","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html","title":{"rendered":"Secure Your Java App with Spring Security, Thymeleaf, and Okta"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>Never Build Auth Again<\/b> &#8211; Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to your app in minutes. <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=Syndication%3EGlobal%3Esecure-java-app-spring-security-thymeleaf-okta-FY18Q4&#038;utm_medium=post&#038;utm_source=java-code-geeks-all-developer\">Create a free developer account today.<\/a><\/span><\/p>\n<p>When you\u2019re building your java app, user management is a critical consideration. It\u2019s common for apps and APIs to partition access to different parts of an application, depending on the roles assigned to a user \u2013 this is role-based access control (RBAC).<\/p>\n<p>This is where Okta comes in \u2013 Okta simplifies this by managing roles within groups (users can belong to one or more groups). With Okta\u2019s Spring Security integration, this process becomes automated through the use of common annotations that map groups to specific roles and either allow or deny access. This is done using common Spring Security annotations, which we\u2019ve outlined below.<\/p>\n<p>To show this in practice, I\u2019ve put together a demo below that walks through a simple, but common scenario. For our example, we\u2019ll look at a mix of unprotected pages, pages that only an authenticated user\u00a0 can access, and pages that require users to have an extra level of authorization before they can access them.<\/p>\n<p>We\u2019ve added all of the code we reference throughout <a href=\"https:\/\/github.com\/oktadeveloper\/okta-spring-security-roles-example\">here.<\/a><\/p>\n<p>If you\u2019re already looking to dive in and get started with built-in RBAC for your Java app, simply wire up your Okta tenant to a Spring Boot application <a href=\"https:\/\/github.com\/okta\/okta-spring-security\">here<\/a>.<\/p>\n<p><em>If you have any questions, contact Okta\u2019s dev support team <a href=\"https:\/\/developer.okta.com\/\">here.<\/a><\/em><\/p>\n<h2>Step One: Configure Your Okta Account<\/h2>\n<p>The first step is setting up your Okta tenant. This way, you can launch the sample app we\u2019ve created and see this in action. Sign up for a developer account <a href=\"https:\/\/developer.okta.com\">here<\/a> and then follow the steps below:<\/p>\n<ol>\n<li>Create an <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> group<\/li>\n<li>Create a <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> group<\/li>\n<li>Create a user who belongs to the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> groups<\/li>\n<li>Create a second user who belongs to both groups<\/li>\n<li>Create an OpenID Connect (OIDC) application<\/li>\n<li>Add the two groups to the application<\/li>\n<li>Configure the default Authorization Server to include group memberships in access tokens<\/li>\n<\/ol>\n<p>Let\u2019s walk through what this looks like:<\/p>\n<h3>Setting Up Groups<\/h3>\n<p>In your Okta Admin Dashboard menu, find <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Users<\/code> and then click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Groups<\/code>. Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Add Group<\/code> and enter <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> in the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Name<\/code> field and add a group description, like: Admins. Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Add Group<\/code> to finish this step.<\/p>\n<p>Follow the same process to add a <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> Group.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70236\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12-1024x748.png\" alt=\"\" width=\"860\" height=\"628\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12-1024x748.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12-768x561.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image12.png 1164w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<h3>Setting Up Users<\/h3>\n<p>Again, navigate to <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Users<\/code> in the Okta Admin Dashboard, but this time click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">People<\/code>. Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Add User<\/code> and fill in the form with the user information. (Use a real email address for either the primary or secondary email address \u2013 and one that you have access to \u2013 so that you can validate the email later.) In the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Groups<\/code> field, add this users to the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> group you created earlier. Make sure you\u2019ve clicked the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Send user activation email now<\/code> checkbox and then click &#8220;Save and Add Another&#8221;.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70237\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14-1024x749.png\" alt=\"\" width=\"860\" height=\"629\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14-1024x749.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14-768x562.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image14.png 1162w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Repeat the steps we outlined above, only this time, add the second user to <em>both<\/em> the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> and <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> groups.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image18.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70238\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image18-1024x745.png\" alt=\"\" width=\"860\" height=\"626\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image18-1024x745.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image18-300x218.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image18-768x559.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Hop over to your email and validate those email addresses. Click the links for both users to activate them.<\/p>\n<h3>Creating an OIDC Application<\/h3>\n<p>Now it\u2019s time to set up your authentication layer.<\/p>\n<p>In the Okta Admin Dashboard, click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Applications<\/code> in the menu and then click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Add Application<\/code>.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70239\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16-1024x745.png\" alt=\"\" width=\"860\" height=\"625\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16-1024x745.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16-300x218.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16-768x559.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image16.png 1166w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Choose <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Web<\/code> and click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Next<\/code>.<\/p>\n<p>When you\u2019re prompted to fill out the form, use these values:<\/p>\n<pre class=\"gutter: false;brush:bash\">| Field\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Value\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| ------------------- | ------------------------------ |\r\n| Name\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Fun with Spring Security Roles |\r\n| Base URIs\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | http:\/\/localhost:8080\/\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| Login redirect URIs | http:\/\/localhost:8080\/\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| Group assignments\u00a0\u00a0 | `admins` and `users`\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| Grant type allowed\u00a0 | Check: `Implicit`\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |<\/pre>\n<p>Once you\u2019re ready, click `Done` and you\u2019ll see the resulting page below:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70240\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15-1024x747.png\" alt=\"\" width=\"860\" height=\"627\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15-1024x747.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15-768x560.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image15.png 1165w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<div class=\"tip\"><strong>Tip<\/strong><br \/>\nThe URIs specified are the Spring Boot defaults. You can easily change these later on.<\/div>\n<p>Before moving on to the next step, scroll down and note the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Client ID<\/code>. You&#8217;ll need it to configure the Spring Boot app.<\/p>\n<h3>\u00a0Setting Up Your Authorization Server<\/h3>\n<p>Next, look for <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">API<\/code> in the Okta Admin Dashboard menu and click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Authorization Servers<\/code> to launch the following:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70241\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5-1024x746.png\" alt=\"\" width=\"860\" height=\"627\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5-1024x746.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5-768x560.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image5.png 1164w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Take note of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Issuer URI<\/code>. You&#8217;ll also need this later to configure the Spring Boot app.<\/p>\n<p>Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">default<\/code> and choose the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Claims<\/code> tab. Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Add Claim<\/code> and fill out the fields as follows:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"gutter: false;brush:bash\">| Field\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Value\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| --------------------- | ------------ |\r\n| Name\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | groups\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| Include in token type | Access Token |\r\n| Value type\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Groups\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| Filter\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Regex .*\u00a0\u00a0\u00a0\u00a0 |\r\n| Include in\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Any scope\u00a0\u00a0\u00a0 |<\/pre>\n<p>Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Create<\/code> to finish this step.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70242\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20-1024x746.png\" alt=\"\" width=\"860\" height=\"627\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20-1024x746.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20-768x560.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image20.png 1165w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Creating this Claim ensures that group membership information is included in the Access Token when a user authenticates. This step is critical to hook into Spring Security\u2019s roles and authorities mechanism.<\/p>\n<h2>Step Two: Configure Your Spring Boot App<\/h2>\n<p>First, clone the at this <a href=\"https:\/\/github.com\/oktadeveloper\/okta-spring-security-roles-example\">link.<\/a><\/p>\n<p>Open the project in your preferred IDE or editor. The screenshots below are from <a href=\"https:\/\/www.jetbrains.com\/idea\/\">here.<\/a><\/p>\n<p>Make a copy of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml.sample<\/code> file and name it <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml<\/code><\/p>\n<p>Remember those values we flagged to save earlier? Update your information with those. Here\u2019s our example:<\/p>\n<pre class=\"gutter: false;brush:bash\">| Name\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Value\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| ----------- | ------------------------------------------------- |\r\n| baseUrl\u00a0\u00a0\u00a0\u00a0 | https:\/\/dev-237330.oktapreview.com\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| issuer\u00a0\u00a0\u00a0\u00a0\u00a0 | https:\/\/dev-237330.oktapreview.com\/oauth2\/default |\r\n| audience\u00a0\u00a0\u00a0 | api:\/\/default\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| clientId\u00a0\u00a0\u00a0 | 0oacdldhkydGGruON0h7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| rolesClaim\u00a0 | groups\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| redirectUri | http:\/\/localhost:8080\/\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |<\/pre>\n<p>Before we jump into the code, let\u2019s see the application in action.<\/p>\n<p>Run this from the command line to get started:<\/p>\n<pre class=\"gutter: false;brush:bash\">mvn spring-boot:run<\/pre>\n<h2>See the App in Action<\/h2>\n<p>Navigate to the home page and click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Login<\/code>.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70243\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13-1024x745.png\" alt=\"\" width=\"860\" height=\"626\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13-1024x745.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13-300x218.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13-768x559.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image13.png 1164w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>To sign in, use the credentials for the user that belongs to the <code class=\"&quot;highlighter-rouge\" style=\"font-size: 13px;\">Users<\/code> group you created in step one. From there, you\u2019ll see that the app shows your user information and displays a row of buttons below it.<\/p>\n<p>These correspond with access permissions within the app. Members of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> group will be able to see the page when <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Users Only<\/code> is clicked. This is the same case for users of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> group, who can see the page when <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Admins Only<\/code> is clicked.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70244\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6-1024x746.png\" alt=\"\" width=\"860\" height=\"627\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6-1024x746.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6-300x219.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6-768x560.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image6.png 1164w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Let\u2019s see how this works.<\/p>\n<p>Click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Users Only<\/code>. You\u2019ll see a page that shows that you\u2019re a member of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> group.<br \/>\nClick <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Back<\/code> and then click <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Admins Only<\/code>. This time, you\u2019ll get a <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">403 Unauthorized<\/code> page because you\u2019re not a member of the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> group.<br \/>\nClick <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Logout<\/code> and sign in again, but this time as the user that belongs to both groups (the second user you created in Step One).<br \/>\nClick <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Admins Only<\/code>.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19.png\"><img decoding=\"async\" class=\"aligncenter wp-image-70245\" style=\"border: none;\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19-1024x745.png\" alt=\"\" width=\"860\" height=\"626\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19-1024x745.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19-300x218.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19-768x559.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/11\/image19.png 1161w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>This time, you\u2019ll see that you are in both the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">admins<\/code> and <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">users<\/code> groups.<\/p>\n<p>Pretty straightforward! Now let\u2019s jump into the code&#8230;<\/p>\n<h2>Step Three: Spring Security Code Review<\/h2>\n<p>This section outlines how Okta groups link up to Spring Security roles.<\/p>\n<p>The <a href=\"https:\/\/github.com\/oktadeveloper\/okta-spring-security-roles-example\">demo<\/a> application\u00a0uses the following:<\/p>\n<ol>\n<li>Spring Boot<\/li>\n<li>Spring Security<\/li>\n<li>Spring Security OAuth2<\/li>\n<li>Okta Spring Security Starter<\/li>\n<li>Thymeleaf Templates<\/li>\n<li>Thymeleaf Extras for Spring Security 4<\/li>\n<li>Okta Sign-In Widget<\/li>\n<\/ol>\n<p>We depend on the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta-spring-security-starter<\/code> (from pom.xml). That\u2019s how the behind-the-scenes magic happens:<\/p>\n<pre class=\"gutter: false;brush:xml\">...\r\n&lt;dependency&gt;\r\n\t&lt;groupId&gt;com.okta.spring&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;okta-spring-security-starter&lt;\/artifactId&gt;\r\n\t&lt;version&gt;0.1.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n...\r\n<\/pre>\n<p>Let&#8217;s start with the Javascript Okta Sign-In Widget and see how it connects the client side to Spring Boot.<\/p>\n<h3>Setting Up the Okta Sign-In Widget<\/h3>\n<p>Here\u2019s how we set up the Okta Sign-In widget in the `login.html` Thymeleaf template:<\/p>\n<pre class=\"gutter: false;brush:js\">$( document ).ready(function() {\r\n    var data = {\r\n        baseUrl: [[${appProperties.baseUrl}]],\r\n        clientId: [[${appProperties.clientId}]],\r\n        redirectUri: [[${appProperties.redirectUri}]],\r\n        authParams: {\r\n            issuer: [[${appProperties.issuer}]],\r\n            responseType: ['token']\r\n        }\r\n    };\r\n    window.oktaSignIn = new OktaSignIn(data);\r\n\r\n    \/\/ Check if we already have an access token\r\n    var token = oktaSignIn.tokenManager.get('token');\r\n    if (token) {\r\n        window.location.href = \"\/authenticated\";\r\n    } else {\r\n        renderWidget();\r\n    }\r\n});<\/pre>\n<p>In lines 3\u20138, you\u2019ll see that we\u2019ve embedded all the settings to connect to our Okta tenant as inline Thymeleaf Template variables. These values are passed in from the Spring Boot controller as part of the model. By doing this, you only have to specify these settings once \u2013 now both the server and client side can make sure of them. We\u2019ll elaborate on how these settings are managed below (they all come from the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml<\/code> file).<\/p>\n<p>After we\u2019ve configured and instantiated the Okta Sign-In Widget, the next step is to check whether or not the user has logged in. Then we take one of two actions. If they have, we send them to the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/authenticated<\/code> page. If they haven\u2019t, we render the widget, which gives the user the opportunity to log in.<\/p>\n<p>Here&#8217;s the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">renderWidget<\/code> function:<\/p>\n<pre class=\"gutter: false;brush:java\">function renderWidget() {\r\n    oktaSignIn.renderEl(\r\n        {el: '#okta-login-container'},\r\n        function (response) {\r\n\r\n            \/\/ check if success\r\n            if (response.status === 'SUCCESS') {\r\n\r\n                \/\/ for our example we have the id token and the access token\r\n                oktaSignIn.tokenManager.add('token', response[0]);\r\n\r\n                if (!document.location.protocol.startsWith('https')) {\r\n                    console.log(\r\n                        'WARNING: You are about to pass a bearer token in a cookie over an insecure\\n' +\r\n                        'connection. This should *NEVER* be done in a production environment per\\n' +\r\n                        'https:\/\/tools.ietf.org\/html\/rfc6750'\r\n                    );\r\n                }\r\n                document.cookie = 'access_token=' + oktaSignIn.tokenManager.get('token').accessToken;\r\n                document.location.href = \"\/authenticated\";\r\n            }\r\n        },\r\n        function (err) {\r\n            \/\/ handle any errors\r\n            console.log(err);\r\n        }\r\n    );\r\n}\r\n<\/pre>\n<p>Once the widget is rendered on the page, the internal logic takes over based on your settings when the user logs in. In this case, you are using <a href=\"https:\/\/tools.ietf.org\/html\/rfc6749#section-1.3.2\">this<\/a> flow and will get back only an access token as specified by the <code class=\"highlighter-rouge\">responseType<\/code> parameter of the configuration.<\/p>\n<p>On successful login, you enter the callback function with a <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">response<\/code> object. The response object has your (or in this case, your user\u2019s) access token.<\/p>\n<p>Line 19 sets a cookie with the access token and line 20 sends the (now authenticated) user to the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/authenticated<\/code> endpoint.<\/p>\n<p>At this point, Spring Security can recognize the authenticated user.<\/p>\n<p>Before we look at Spring Security roles, let&#8217;s see how Spring Security deals with the access token.<\/p>\n<h3>Spring Security Token Extractor<\/h3>\n<p>By default, the Spring Security OAuth 2.0 plugin processes access tokens coming in on an <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Authorization<\/code> header as a bearer token. This is fine for applications that are creating RESTful responses for clients, such as an Angular client.<\/p>\n<p>For this example, I kept the architecture and amount of Javascript minimal, so I wanted full page transitions. This is a little old-school, but it keeps the example code tight and small.<\/p>\n<p>In order for Spring Security to recognize that a user has authenticated, we need it to be able to handle the token coming in on a cookie.<\/p>\n<p>Fortunately, Spring Security makes it pretty easy to override the default behavior by setting a <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">TokenExtractor<\/code>. Here&#8217;s the code that makes this happen from <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">OktaSpringSecurityRolesExampleApplication<\/code>:<\/p>\n<pre class=\"gutter: false;brush:java\">@Bean\r\nprotected ResourceServerConfigurerAdapter resourceServerConfigurerAdapter() {\r\n    return new ResourceServerConfigurerAdapter() {\r\n\r\n        ...\r\n\r\n        @Override\r\n        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {\r\n            resources.tokenExtractor(new TokenExtractor() {\r\n\r\n                @Override\r\n                public Authentication extract(HttpServletRequest request) {\r\n                    String tokenValue = findCookie(ACCESS_TOKEN_COOKIE_NAME, request.getCookies());\r\n                    if (tokenValue == null) { return null; }\r\n\r\n                    return new PreAuthenticatedAuthenticationToken(tokenValue, \"\");\r\n                }\r\n\r\n                ...\r\n            });\r\n        }\r\n    };\r\n}\r\n<\/pre>\n<p>What this does is pull the access token from the list of cookies on the incoming request, if it can. Then the parsing and validation is done automatically. Voila!<\/p>\n<h3>Establishing Role Based Access Controls<\/h3>\n<p>In the application setup, you define which paths are open. All other paths require an authenticated session at least.<\/p>\n<p>Here&#8217;s another excerpt from <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">OktaSpringSecurityRolesExampleApplication<\/code>:<\/p>\n<pre class=\"gutter: false;brush:java\">@Bean\r\nprotected ResourceServerConfigurerAdapter resourceServerConfigurerAdapter() {\r\n    return new ResourceServerConfigurerAdapter() {\r\n\r\n        @Override\r\n        public void configure(HttpSecurity http) throws Exception {\r\n            http.authorizeRequests()\r\n                .antMatchers(\"\/\", \"\/login\", \"\/images\/**\").permitAll()\r\n                .and()\r\n                .exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);\r\n        }\r\n        ...\r\n    };\r\n}<\/pre>\n<p>In this case, you are telling Spring Security to let any unauthenticated user access the home page (<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/<\/code>), the login page (<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/login<\/code>), and anything that comes from the static images folder. This means that every other path is automatically restricted by default.<\/p>\n<p>At this point, you also define a custom access-denied handler.<\/p>\n<pre class=\"gutter: false;brush:java\">@Controller\r\npublic class SecureController {\r\n\r\n    @Autowired\r\n    protected AppProperties appProperties;\r\n\r\n    @RequestMapping(\"\/authenticated\")\r\n    public String authenticated(Model model) {\r\n        model.addAttribute(\"appProperties\", appProperties);\r\n        return \"authenticated\";\r\n    }\r\n\r\n    @RequestMapping(\"\/users\")\r\n    @PreAuthorize(\"hasAuthority('users')\")\r\n    public String users() {\r\n        return \"roles\";\r\n    }\r\n\r\n    @RequestMapping(\"\/admins\")\r\n    @PreAuthorize(\"hasAuthority('admins')\")\r\n    public String admins() {\r\n        return \"roles\";\r\n    }\r\n\r\n    @RequestMapping(\"\/403\")\r\n    public String error403() {\r\n        return \"403\";\r\n    }\r\n}<\/pre>\n<p>Within this controller, we\u2019ve defined four paths, which all require an authenticated user at a minimum.<\/p>\n<p>The real value comes in with the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/users<\/code> and <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/admins<\/code> paths. Notice that they both have the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@PreAuthorize<\/code> annotation. This means that <a href=\"https:\/\/docs.spring.io\/spring\/docs\/current\/spring-framework-reference\/core.html#expressions\">the<\/a> expression that follows must be satisfied before the method will even be entered. The <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasAuthority<\/code> function confirms whether the authenticated user belongs to those roles. In this example, these are automatically mapped to the Okta groups we created previously, which is why it was important to include the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">groups<\/code> claim in the access token from Okta.<\/p>\n<p>While this involves a bit of set-up, now you have role-based access control with just one line of code!<\/p>\n<h2>End-to-End Configuration<\/h2>\n<p>On the client side, we have a set of HTML pages in the form of Thymeleaf templates served from the application itself. Because of this, it makes sense to have a single source for configuration values required by both the client and server.<\/p>\n<p>This is easy with Spring\u2019s <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@Component<\/code> and <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@ConfigurationProperties<\/code> annotations.<\/p>\n<p>Here&#8217;s the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">AppProperties<\/code> class:<\/p>\n<pre class=\"gutter: false;brush:java\">@Component\r\n@ConfigurationProperties(\"okta.oauth\")\r\npublic class AppProperties {\r\n    private String issuer;\r\n    private String audience;\r\n    private String clientId;\r\n    private String rolesClaim;\r\n    private String baseUrl;\r\n    private String redirectUri;\r\n\r\n    ... getters and setters ...\r\n}<\/pre>\n<p>The <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@ConfigurationProperties<\/code> tells Spring to pull in all the properties from the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.yml <\/code>file that belong to the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta.oauth<\/code> key.<\/p>\n<p>The <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@Component<\/code> annotation causes Spring to instantiate this Object and make it available for auto-wiring elsewhere.<\/p>\n<p>Take a look at this snippet from the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">HomeController<\/code>:<\/p>\n<pre class=\"gutter: false;brush:java\">@Controller\r\npublic class HomeController {\r\n\r\n    @Autowired\r\n    protected AppProperties appProperties;\r\n\r\n    ...\r\n\r\n    @RequestMapping(\"\/login\")\r\n    public String login(Model model) {\r\n        model.addAttribute(\"appProperties\", appProperties);\r\n        return \"login\";\r\n    }\r\n}<\/pre>\n<p>Before returning the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">login<\/code> view when the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/login <\/code>endpoint is hit, the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">AppProperties<\/code> object (autowired in on lines 4 &amp; 5) is added to the model.<\/p>\n<p>This is what makes it available to the Thymeleaf template as you saw before:<\/p>\n<pre class=\"gutter: false;brush:js\">&lt;script th:inline=\"javascript\"&gt;\r\n    \/*&lt;![CDATA[*\/\r\n    $( document ).ready(function() {\r\n        var data = {\r\n            baseUrl: [[${appProperties.baseUrl}]],\r\n            clientId: [[${appProperties.clientId}]],\r\n            redirectUri: [[${appProperties.redirectUri}]],\r\n            authParams: {\r\n                issuer: [[${appProperties.issuer}]],\r\n                responseType: ['token']\r\n            }\r\n        };\r\n        window.oktaSignIn = new OktaSignIn(data);\r\n        ...\r\n    });\r\n    ...\r\n    \/*]]&gt;*\/\r\n&lt;\/script&gt;<\/pre>\n<h2>Start Coding!<\/h2>\n<p>And that\u2019s it! Give it a go and let me know how it goes! I\u2019m on <a href=\"https:\/\/twitter.com\/afitnerd\">Twitter.<\/a><\/p>\n<p>While I\u2019ve outlined the benefits of using Okta\u2019s Groups mechanism with Spring Security\u2019s role-based access control, Okta\u2019s Java dev team is working hard on our next generation SDK and integrations as well. Keep an eye out for upcoming releases of the new Okta Java Spring Boot Integration, which will have have support for other OIDC workflows, including <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">code<\/code> as well as hosted, configurable login and registration views.<\/p>\n<p><em>This post has been adapted from <a href=\"https:\/\/developer.okta.com\/blog\/2017\/10\/13\/okta-groups-spring-security\">here.<\/a><\/em><\/p>\n<p><span style=\"font-size: 20px;\"><b>Never Build Auth Again<\/b> &#8211; Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to your app in minutes. <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=Syndication%3EGlobal%3Esecure-java-app-spring-security-thymeleaf-okta-FY18Q4&#038;utm_medium=post&#038;utm_source=java-code-geeks-all-developer\">Create a free developer account today.<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Never Build Auth Again &#8211; Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to your app in minutes. Create a free developer account today. When you\u2019re building your java app, user management is a critical consideration. It\u2019s common for apps and APIs to partition access to &hellip;<\/p>\n","protected":false},"author":1062,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[1594,297,1615,30,125,739],"class_list":["post-70234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-okta","tag-security","tag-sponsored","tag-spring","tag-spring-security","tag-thymeleaf"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html\" \/>\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=\"2017-11-06T17:40:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-11-14T07:53:49+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=\"Micah Silverman\" \/>\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=\"Micah Silverman\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html\"},\"author\":{\"name\":\"Micah Silverman\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fd211fe0d3a9791d30dd0ca5276d9660\"},\"headline\":\"Secure Your Java App with Spring Security, Thymeleaf, and Okta\",\"datePublished\":\"2017-11-06T17:40:28+00:00\",\"dateModified\":\"2017-11-14T07:53:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html\"},\"wordCount\":1909,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Okta\",\"Security\",\"Sponsored\",\"Spring\",\"Spring Security\",\"Thymeleaf\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html\",\"name\":\"Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2017-11-06T17:40:28+00:00\",\"dateModified\":\"2017-11-14T07:53:49+00:00\",\"description\":\"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#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:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/11\\\/secure-java-app-spring-security-thymeleaf-okta.html#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\":\"Secure Your Java App with Spring Security, Thymeleaf, and Okta\"}]},{\"@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\\\/fd211fe0d3a9791d30dd0ca5276d9660\",\"name\":\"Micah Silverman\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g\",\"caption\":\"Micah Silverman\"},\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/micah-silverman\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks","description":"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to","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:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html","og_locale":"en_US","og_type":"article","og_title":"Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks","og_description":"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to","og_url":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-11-06T17:40:28+00:00","article_modified_time":"2017-11-14T07:53:49+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":"Micah Silverman","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Micah Silverman","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html"},"author":{"name":"Micah Silverman","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fd211fe0d3a9791d30dd0ca5276d9660"},"headline":"Secure Your Java App with Spring Security, Thymeleaf, and Okta","datePublished":"2017-11-06T17:40:28+00:00","dateModified":"2017-11-14T07:53:49+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html"},"wordCount":1909,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Okta","Security","Sponsored","Spring","Spring Security","Thymeleaf"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html","url":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html","name":"Secure Your Java App with Spring Security, Thymeleaf, and Okta - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2017-11-06T17:40:28+00:00","dateModified":"2017-11-14T07:53:49+00:00","description":"Never Build Auth Again - Love building user management? With Okta, you can add social login, multi-factor authentication, and OpenID Connect support to","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#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:\/\/www.javacodegeeks.com\/2017\/11\/secure-java-app-spring-security-thymeleaf-okta.html#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":"Secure Your Java App with Spring Security, Thymeleaf, and Okta"}]},{"@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\/fd211fe0d3a9791d30dd0ca5276d9660","name":"Micah Silverman","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fdd31b256ed406e9651be5c9f709a208535846dc978cc1b1211f9ca2473709de?s=96&d=mm&r=g","caption":"Micah Silverman"},"url":"https:\/\/www.javacodegeeks.com\/author\/micah-silverman"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/70234","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\/1062"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=70234"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/70234\/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=70234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=70234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=70234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}