<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Micah Silverman</title>
    <description>The latest articles on Forem by Micah Silverman (@dogeared).</description>
    <link>https://forem.com/dogeared</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F100147%2F86108f26-a90d-4aa6-9b71-5aada5297377.jpeg</url>
      <title>Forem: Micah Silverman</title>
      <link>https://forem.com/dogeared</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dogeared"/>
    <language>en</language>
    <item>
      <title>Easy Single Sign-On with Spring Boot and OAuth 2.0</title>
      <dc:creator>Micah Silverman</dc:creator>
      <pubDate>Thu, 02 May 2019 05:00:00 +0000</pubDate>
      <link>https://forem.com/oktadev/easy-single-sign-on-with-spring-boot-and-oauth-2-0-13ig</link>
      <guid>https://forem.com/oktadev/easy-single-sign-on-with-spring-boot-and-oauth-2-0-13ig</guid>
      <description>&lt;p&gt;Single sign-on used to be the “Holy Grail” of enterprise size companies and was usually only available to companies that could afford it. Nowadays, we take SSO as a matter of course. For instance, you would think it's completely weird (and unpleasant) if you logged into Gmail and then had to log in again when you went to Google Docs.&lt;/p&gt;

&lt;p&gt;But, what about building custom applications for developers? SSO was still in the domain of the enterprise with everything from proprietary solutions to SAML, which usually required complex configuration of on-premises solutions.&lt;/p&gt;

&lt;p&gt;Now, with standards like OAuth 2.0 and OpenID Connect and service providers, like &lt;a href="https://developer.okta.com/"&gt;Okta&lt;/a&gt;, it’s a snap for developers to incorporate SSO into their apps, whether it’s a hobby project or an enterprise grade application.&lt;/p&gt;

&lt;p&gt;In this post, I’ll introduce OpenID Connect - the key enabling technology for delegated authentication and SSO - and then jump into a code example with Spring Boot where you can see SSO in action across multiple applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approaches to Single Sign-On with OAuth 2.0 and OpenID Connect
&lt;/h2&gt;

&lt;p&gt;With OIDC, SSO is often accomplished by linking multiple applications through a single defined OpenID Connect application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--no5auREF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/23f402b96ce8cd1c3dd9cdcedb9eec525963cc79/828e0/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_1-6045009e1110b8a4cf86dfebc459558cc495db99f8114f9bb2469163ff58eaa1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--no5auREF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/23f402b96ce8cd1c3dd9cdcedb9eec525963cc79/828e0/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_1-6045009e1110b8a4cf86dfebc459558cc495db99f8114f9bb2469163ff58eaa1.png" alt="Level 1 SSO"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the diagram above, you can see that you achieve SSO because you authenticate with Client App 1 via OIDC App 1 and Client App 2 is connected to the same OIDC App 1 application.&lt;/p&gt;

&lt;p&gt;Let’s call this “Level 1” SSO.&lt;/p&gt;

&lt;p&gt;“Level 2” is being able to connect multiple client applications to multiple OIDC applications and still accomplish SSO. Here’s what this looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o9KdDmmg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/dd0033c8c23a7aacbab380ad8f313b1124f1ebf5/4e05b/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_2-41e505cfbb39dbfd1fb5598f72412cee2b3e409e1d53839ac324015e967960dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o9KdDmmg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/dd0033c8c23a7aacbab380ad8f313b1124f1ebf5/4e05b/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_2-41e505cfbb39dbfd1fb5598f72412cee2b3e409e1d53839ac324015e967960dd.png" alt="Level 2 SSO"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A successful interaction with OpenID Connect results in an ID Token (identity token) being passed back to the application.&lt;/p&gt;

&lt;p&gt;In this case, you may have different requirements for the information included in the ID Token that comes back between OIDC App 1 and OIDC App 2. Each Spring Boot application gets its own ID Token and yet you only have to authenticate once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up Your App for Next Level Single Sign-On with OAuth and OpenID Connect
&lt;/h2&gt;

&lt;p&gt;Head on over to &lt;a href="https://developer.okta.com/signup/"&gt;developer.okta.com&lt;/a&gt; to create yourself a free-forever developer account. Look for the email to complete the initialization of your Okta org.&lt;/p&gt;

&lt;p&gt;You’ll set up two OpenID Connect applications next.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Applications&lt;/strong&gt; in the admin console and click: &lt;strong&gt;Add Application&lt;/strong&gt;. Choose &lt;strong&gt;Web&lt;/strong&gt; and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Populate the fields with these values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;OIDC App 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Base URIs&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Login redirect URIs&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:8080/login/oauth2/code/okta"&gt;http://localhost:8080/login/oauth2/code/okta&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Click &lt;strong&gt;Done&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Scroll down and copy the &lt;code&gt;Client ID&lt;/code&gt; and &lt;code&gt;Client Secret&lt;/code&gt;. You’ll use those values shortly.&lt;/p&gt;

&lt;p&gt;Create a second app in the same way with these values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;OIDC App 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Base URIs&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:8081"&gt;http://localhost:8081&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Login redirect URIs&lt;/td&gt;
&lt;td&gt;&lt;a href="http://localhost:8081/login/oauth2/code/okta"&gt;http://localhost:8081/login/oauth2/code/okta&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Copy the &lt;code&gt;Client ID&lt;/code&gt; and &lt;code&gt;Client Secret&lt;/code&gt; values here as well.&lt;/p&gt;

&lt;p&gt;Next, you’ll set up some Authorization Servers with custom claims and access policies. This drives whether or not Okta will issue a token when one is requested.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;strong&gt;API &amp;gt; Authorization Servers&lt;/strong&gt;. Click &lt;strong&gt;Add Authorization Server&lt;/strong&gt;. Fill in the values according to this table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;OIDC App 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audience&lt;/td&gt;
&lt;td&gt;api://oidcapp1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Description&lt;/td&gt;
&lt;td&gt;OIDC App 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Click &lt;strong&gt;Done&lt;/strong&gt;. Click the &lt;strong&gt;Claims&lt;/strong&gt; tab. Click &lt;strong&gt;Add Claim&lt;/strong&gt;. Fill in the fields with these values (leave those not mentioned as their defaults):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;appName&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Include in token type&lt;/td&gt;
&lt;td&gt;ID Token Always&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;“OIDC App 1”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note the double quotes (“) in the “OIDC App 1”.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Access Policies&lt;/strong&gt; tab. Click &lt;strong&gt;Add Policy&lt;/strong&gt;. Enter: &lt;code&gt;OIDC App 1&lt;/code&gt;, for the &lt;strong&gt;Name&lt;/strong&gt; and &lt;strong&gt;Description&lt;/strong&gt; fields. For the &lt;strong&gt;Assign to&lt;/strong&gt; field, choose &lt;strong&gt;The following clients&lt;/strong&gt;. Start typing: &lt;code&gt;OIDC&lt;/code&gt; in the input area and click &lt;strong&gt;Add&lt;/strong&gt; to the right of &lt;code&gt;OIDC App 1&lt;/code&gt;. Click &lt;strong&gt;Create Policy&lt;/strong&gt;. This binds the policy to your first OIDC app.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Add Rule&lt;/strong&gt;. Enter: &lt;code&gt;OIDC App 1&lt;/code&gt; for the &lt;strong&gt;Name&lt;/strong&gt; field. Deselect all the grant types except for &lt;strong&gt;Authorization Code&lt;/strong&gt;. Click &lt;strong&gt;Create Rule&lt;/strong&gt;. This ensures that the request must be the Authorization Code flow in order for Okta to create tokens (More on the Authorization Code Flow below).&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Settings&lt;/strong&gt; tab and copy the &lt;strong&gt;Issuer&lt;/strong&gt; URL. You’ll make use of this value shortly.&lt;/p&gt;

&lt;p&gt;You’re now going to repeat everything for a second Authorization Server, only this time, it will be bound to your second OIDC App.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;strong&gt;API &amp;gt; Authorization Servers&lt;/strong&gt;. Click &lt;strong&gt;Add Authorization Server&lt;/strong&gt;. Fill in the values according to this table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;OIDC App 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audience&lt;/td&gt;
&lt;td&gt;api://oidcapp2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Description&lt;/td&gt;
&lt;td&gt;OIDC App 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Click &lt;strong&gt;Done&lt;/strong&gt;. Click the &lt;strong&gt;Claims&lt;/strong&gt; tab. Click &lt;strong&gt;Add Claim&lt;/strong&gt;. Fill in the fields with these values (leave those not mentioned as their defaults):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;appName&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Include in token type&lt;/td&gt;
&lt;td&gt;ID Token Always&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;“OIDC App 2”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note the double quotes (“) in the “OIDC App 2”.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Access Policies&lt;/strong&gt; tab. Click &lt;strong&gt;Add Policy&lt;/strong&gt;. Enter: &lt;code&gt;OIDC App 2&lt;/code&gt;, for the &lt;strong&gt;Name&lt;/strong&gt; and &lt;strong&gt;Description&lt;/strong&gt; fields. For the &lt;strong&gt;Assign to&lt;/strong&gt; field, choose &lt;strong&gt;The following clients&lt;/strong&gt;. Start typing: &lt;code&gt;OIDC&lt;/code&gt; in the input area and click &lt;strong&gt;Add&lt;/strong&gt; to the right of &lt;code&gt;OIDC App 2&lt;/code&gt;. Click &lt;strong&gt;Create Policy&lt;/strong&gt;. This binds the policy to your second OIDC app.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Add Rule&lt;/strong&gt;. Enter: &lt;code&gt;OIDC App 2&lt;/code&gt; for the &lt;strong&gt;Name&lt;/strong&gt; field. Deselect all the grant types except for &lt;strong&gt;Authorization Code&lt;/strong&gt;. Click &lt;strong&gt;Create Rule&lt;/strong&gt;. This ensures that the request must be the Authorization Code flow in order for Okta to create tokens.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Settings&lt;/strong&gt; tab and copy the &lt;strong&gt;Issuer&lt;/strong&gt; URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Spring Boot’s OAuth integration for Single Sign-On
&lt;/h2&gt;

&lt;p&gt;Now that you have all the configuration in place, you can see “next level” single sign-on in action.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/oktadeveloper/okta-spring-boot-oidc-sso-example"&gt;github project&lt;/a&gt; includes a shell script to launch the app. This works on Mac and Linux. If you’re on another platform, simply examine the last line of the script to launch the application. Open up two terminal windows. Execute the following in the first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./run_app.sh &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ci&lt;/span&gt; &amp;lt;client &lt;span class="nb"&gt;id&lt;/span&gt;, oidc app 1&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cs&lt;/span&gt; &amp;lt;client secret, oidc app 1&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--is&lt;/span&gt; &amp;lt;issuer, oidc app 1&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--po&lt;/span&gt; 8080

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Execute the following in the second terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./run_app.sh &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ci&lt;/span&gt; &amp;lt;client &lt;span class="nb"&gt;id&lt;/span&gt;, oidc app 2&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cs&lt;/span&gt; &amp;lt;client secret, oidc app 2&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--is&lt;/span&gt; &amp;lt;issuer, oidc app 2&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--po&lt;/span&gt; 8081

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Launch your browser and navigate to &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;. You’ll immediately be redirected to authenticate. After you enter your username and password, you should see your name and the app’s name: OIDC App 1. If you don’t see the app name, then it’s likely you didn’t configure the custom claim correctly. You’ll also see the raw ID Token in &lt;a href="https://tools.ietf.org/html/rfc7519"&gt;JSON Web Token&lt;/a&gt; format. You can copy and paste the JWT to &lt;a href="https://jsonwebtoken.io"&gt;jsonwebtoken.io&lt;/a&gt; and see its contents, which includes the &lt;code&gt;appName&lt;/code&gt; claim.&lt;/p&gt;

&lt;p&gt;Open a second tab in your browser and navigate to &lt;a href="http://localhost:8081"&gt;http://localhost:8081&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should NOT be required to authenticate again and you should see your name, the app’s name: OIDC App 2, and another JWT.&lt;/p&gt;

&lt;p&gt;This is Single Sign-On in action. And, you’re using two separate spring boot apps, connecting to two different Authorization Servers, bound to two different OIDC apps. That’s next level SSO!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pJzZETmL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/7e157d46bdce9770f7714166856b1ad68996f9f6/f6c65/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_in_action-0b9d2bc8e40a4115aa80281d51064cf32be7161410ef00a8d9e500177c35a395.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pJzZETmL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/7e157d46bdce9770f7714166856b1ad68996f9f6/f6c65/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/oidc_sso_in_action-0b9d2bc8e40a4115aa80281d51064cf32be7161410ef00a8d9e500177c35a395.png" alt="Level 2 SSO in Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Spring Security with OAuth for Easy Java
&lt;/h2&gt;

&lt;p&gt;It’s Okta’s cloud service for OIDC (which rides on top of OAuth) and SSO that makes this all work. Okta’s &lt;a href="https://github.com/okta/okta-spring-boot"&gt;Spring Boot Starter&lt;/a&gt; combined with the latest version of &lt;a href="https://spring.io/projects/spring-security"&gt;Spring Security&lt;/a&gt; makes the code super simple.&lt;/p&gt;

&lt;p&gt;There’s only three dependencies in the whole project: &lt;code&gt;spring-boot-starter-web&lt;/code&gt;, &lt;code&gt;spring-boot-starter-thymeleaf&lt;/code&gt; and &lt;code&gt;okta-spring-boot-starter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spring-boot-starter-web&lt;/code&gt; gives the application a &lt;a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc"&gt;Model-View-Controller&lt;/a&gt; framework. &lt;code&gt;spring-boot-starter-thymeleaf&lt;/code&gt; is a &lt;a href="https://www.thymeleaf.org/"&gt;templating engine&lt;/a&gt; that integrates with Spring and is the View part of the MVC framework. &lt;code&gt;okta-spring-boot-starter&lt;/code&gt; brings in Spring Security, so you don’t have to define it as another dependency.&lt;/p&gt;

&lt;p&gt;With the Okta Spring Boot Starter, you only need three bits of information to integrate with Okta: &lt;code&gt;client id&lt;/code&gt;, &lt;code&gt;client secret&lt;/code&gt; and &lt;code&gt;issuer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Spring Security requires authentication by default, so there’s no additional configuration needed in this example.&lt;/p&gt;

&lt;p&gt;Take a look at the &lt;code&gt;HomeController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ModelAndView&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@AuthenticationPrincipal&lt;/span&gt; &lt;span class="nc"&gt;OidcUser&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nc"&gt;ModelAndView&lt;/span&gt; &lt;span class="n"&gt;mav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ModelAndView&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
     &lt;span class="n"&gt;mav&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserInfo&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
     &lt;span class="n"&gt;mav&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"idToken"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIdToken&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getTokenValue&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
     &lt;span class="n"&gt;mav&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setViewName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"home"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mav&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By the time this method is entered, Spring Security has already managed authentication via the Authorization Code flow. an &lt;code&gt;OidcUser&lt;/code&gt; object is automatically passed into the method, which represents all of the parsed claims from the ID Token as well as the ID Token JWT itself. The user info and raw JWT are retrieved from the &lt;code&gt;OidcUser&lt;/code&gt; and added to the model. The method then renders the view: home.html.&lt;/p&gt;

&lt;p&gt;Take a look at the heart of &lt;code&gt;home.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;th:if=&lt;/span&gt;&lt;span class="s"&gt;"${user.claims.containsKey('appName')}"&lt;/span&gt;
     &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-success text-center"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;th:text=&lt;/span&gt;&lt;span class="s"&gt;"${user.claims.appName}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;p/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;th:if=&lt;/span&gt;&lt;span class="s"&gt;"${user.claims.containsKey('name')}"&lt;/span&gt;
     &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-primary text-center"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;th:inline=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Welcome [[${user.claims.name}]]!&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-secondary text-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;th:inline=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-break"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"overflow-wrap: anywhere"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         [[${idToken}]]
     &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;th:if&lt;/code&gt; in the first div is Thymeleaf templating to guard against you not having set the &lt;code&gt;appName&lt;/code&gt; custom claim correctly. Assuming it exists, &lt;code&gt;appName&lt;/code&gt; is rendered using &lt;code&gt;user.claims.appName&lt;/code&gt; from the model that was passed into this view.&lt;/p&gt;

&lt;p&gt;The second div shows the user’s name.&lt;/p&gt;

&lt;p&gt;The third div shows the raw JWT that was added to the model in the controller above.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Five-Minute Overview of OpenID Connect
&lt;/h2&gt;

&lt;p&gt;With a new perspective on single sign-on and a working Spring Boot app under our belts, let’s dig into OIDC a little deeper.&lt;/p&gt;

&lt;p&gt;OpenID Connect is an identity and authentication layer that rides on top of OAuth 2.0. In addition to “knowing” who you are, you can use OIDC for Single Sign-On. It’s especially easy with Spring Boot and Okta.&lt;/p&gt;

&lt;p&gt;OIDC is built for web applications as well as native and mobile apps. It’s a modern approach to authentication that we developed by Microsoft, Google and others. It supports delegated authentication. This means that I can provide my credentials to my authentication provider of choice (like Okta) and then my custom application (like a Spring Boot app) gets an assertion in the form of an ID Token to prove that I successfully authenticated. The Spring Boot app never sees the username and password. This is a great approach for modern apps where you want to separate concerns, such as authentication, from the business logic of the application.&lt;/p&gt;

&lt;p&gt;As a developer, I know that I need authentication. But, I’ve seen enough horror stories from breaches over the years that I am happy to not handle credentials directly.&lt;/p&gt;

&lt;p&gt;OpenID Connect uses “flows” to accomplish delegated authentication. This is simply the steps taken to get from an unauthenticated state in the application to an authenticated state.&lt;/p&gt;

&lt;p&gt;Let’s walk through a sequence diagram of what an OIDC flow looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iLRUXeG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/17d11e48e8583bcff8206c698039f1fcd9205400/56b07/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/auth_code_flow-f27567f5419867eb3b49d99ea4cc4a5067e32e306a8311ba087de618ccea6e63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iLRUXeG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/17d11e48e8583bcff8206c698039f1fcd9205400/56b07/assets-jekyll/blog/spring-boot-single-sign-on-oauth-2/auth_code_flow-f27567f5419867eb3b49d99ea4cc4a5067e32e306a8311ba087de618ccea6e63.png" alt="Authorization Code Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This flow is called the Authorization Code Flow and is the most secure flow for end users. It’s the one you’ve been using in the &lt;a href="https://github.com/oktadeveloper/okta-spring-boot-oidc-sso-example"&gt;code example&lt;/a&gt; that goes along with this post. The goal of the flow is to get tokens over to the Spring Boot app as proof of identity.&lt;/p&gt;

&lt;p&gt;You kick off the flow from the application in your browser. It sends a request to the Authorization Server (Okta) which includes a redirect_uri value. This is so that after you’ve authenticated, Okta can send you back to the right spot in your application with an Authorization Code.&lt;/p&gt;

&lt;p&gt;The Spring Boot app can now exchange the Authorization Code for tokens from Okta.&lt;/p&gt;

&lt;p&gt;Why this dance? Your Spring Boot app never sees the credentials. Notice on step 5, the credentials are submitted directly to Okta. The Authorization code is redirected back through the browser (where the request was initiated). But, we don’t want the browser to get the tokens directly. It’s safer for the application under your control - the Spring Boot application - to get the tokens from Okta. That’s why it’s the Spring Boot application that exchanges the code for the tokens.&lt;/p&gt;

&lt;p&gt;To learn more about OAuth 2.0 and OIDC, check out these blog posts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1"&gt;An OpenID Connect Primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2019/03/12/oauth2-spring-security-guide"&gt;A Quick Guide to OAuth 2.0 with Spring Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2019/03/05/spring-boot-migration"&gt;Migrate Your Spring Boot App to the Latest and Greatest Spring Security and OAuth 2.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn More About Secure Single Sign-on, OAuth 2.0, and Spring Boot
&lt;/h2&gt;

&lt;p&gt;The Okta Spring Boot Starter enables you to integrate your Spring Boot apps with Okta with just a few lines of code and three configuration properties.&lt;/p&gt;

&lt;p&gt;Along with our Spring Boot Starter, Okta’s OpenID Connect service not only conforms to the standard, but gives you a sophisticated Single Sign-On experience where the same user can access many different OIDC applications, each with their own set of requirements and configuration. Remember: OIDC rides on top of OAuth 2.0 - it’s not standalone. Whereas OAuth focuses exclusively on authorization, OIDC explicitly adds identity and authentication concerns.&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about OAuth and Spring Boot you might be interested in these other posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/04/02/client-creds-with-spring-boot"&gt;Secure Server-to-Server Communication with Spring Boot and OAuth 2.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/12/13/oauth-2-for-native-and-mobile-apps"&gt;OAuth 2.0 for Native and Mobile Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead"&gt;Is the OAuth 2.0 Implicit Flow Dead?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like what you learned today? Follow us on &lt;a href="https://twitter.com/oktadev"&gt;Twitter&lt;/a&gt;, and subscribe to our &lt;a href="https://www.youtube.com/channel/UC5AMiWqFVFxF1q9Ya1FuZ_Q"&gt;YouTube channel&lt;/a&gt; for more awesome content!&lt;/p&gt;

</description>
      <category>security</category>
      <category>springboot</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Build a One-time Password Token for MFA with Okta</title>
      <dc:creator>Micah Silverman</dc:creator>
      <pubDate>Thu, 30 Aug 2018 05:00:00 +0000</pubDate>
      <link>https://forem.com/oktadev/build-a-one-time-password-token-for-mfa-with-okta-1i4d</link>
      <guid>https://forem.com/oktadev/build-a-one-time-password-token-for-mfa-with-okta-1i4d</guid>
      <description>&lt;p&gt;Okta has a great multi-factor authentication (MFA) service that you can use right away with a &lt;a href="https://developer.okta.com/signup/" rel="noopener noreferrer"&gt;free developer account&lt;/a&gt;. It provides additional security by requiring a second factor after authentication and supports a variety of factor types including SMS, soft tokens like Google Authenticator, hard tokens like Yubikey and the Okta Verify soft token with push notification.&lt;/p&gt;

&lt;p&gt;Google Authenticator and Okta Verify are a type of factor called time-based one-time password (TOTP) tokens. They use an algorithm based on a shared secret and a system clock with a high degree of precision. Okta adds an additional level of convenience without sacrificing security by supporting push notifications in the Okta Verify mobile app.&lt;/p&gt;

&lt;p&gt;Okta Verify uses a QR Code to read in the shared secret when enrolling in MFA.&lt;/p&gt;

&lt;p&gt;In this post, I use the shared secret in a less-convenient but fun way, while still keeping the same level of security. The &lt;a href="https://arduboy.com/" rel="noopener noreferrer"&gt;ArduBoy project&lt;/a&gt; combines an Arduino microprocessor with a monochrome OLED screen and a set of buttons that look suspiciously like a classic Nintendo GameBoy. All this fits into a credit card size form-factor. This open-source programming platform makes for the perfect vehicle to use the TOTP standard to create a hardware and software based hybrid token for MFA.&lt;/p&gt;

&lt;p&gt;Well, maybe not perfect. But, fun!&lt;/p&gt;



&lt;p&gt;The biggest challenge is that when you turn off an ArduBoy, it’s &lt;em&gt;really&lt;/em&gt; off. There’s no realtime clock that continues to run when the ArduBoy is off. We take this for granted on our computers or mobile devices that either have hardware to keep the clock running, have the ability to automatically set the time over a network on boot or both. Not so with the ArduBoy! In order to really use this as your go-to TOTP device, you need to keep it on and charge it before it dies.&lt;/p&gt;

&lt;p&gt;What the application does to mitigate this is use the onboard EEPROM (Electrically Erasable Programmable Read-Only Memory) to (a) save the secret and (b) save the last date and time set. The next time you turn on the ArduBoy, it checks to see if a secret has been set. If so, it goes directly to setting the date and time. On the date and time setting screen, it starts with the last set date and time to make it easier to update.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fardutoken-fade269e61f766f5d7b006b97a369520efbd963164d04da85aed70d8eeb8c01d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fardutoken-fade269e61f766f5d7b006b97a369520efbd963164d04da85aed70d8eeb8c01d.png" alt="Ardu Token" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a fun way to learn a little about TOTP and see it working against a real Okta organization.&lt;/p&gt;

&lt;p&gt;In “real life”, you’ll want to use the Okta Verify mobile app (available on &lt;a href="https://itunes.apple.com/us/app/okta-verify/id490179405?mt=8" rel="noopener noreferrer"&gt;iOS&lt;/a&gt; and &lt;a href="https://play.google.com/store/apps/details?id=com.okta.android.auth&amp;amp;hl=en_US" rel="noopener noreferrer"&gt;Android&lt;/a&gt;). There’s a lot less manual labor involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Up and Running with an Okta Verify Token
&lt;/h2&gt;

&lt;p&gt;The source code (including a pre-built binary) can be found on the &lt;a href="https://github.com/oktadeveloper/okta-ardu-token-example" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have an ArduBoy and want to see the app running, you can install the latest binary &lt;code&gt;.hex&lt;/code&gt; file directly.&lt;/p&gt;

&lt;p&gt;You can also drop the &lt;code&gt;.hex&lt;/code&gt; file right onto the &lt;a href="https://felipemanga.github.io/ProjectABE/" rel="noopener noreferrer"&gt;ProjectABE&lt;/a&gt; ArduBoy emulator site to see it in action without having an actual ArduBoy yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; ProjectABE does not have the ability to save data to the &lt;a href="https://www.arduino.cc/en/Reference/EEPROM" rel="noopener noreferrer"&gt;EEPROM&lt;/a&gt;. So, if you restart the application there, you’ll need to re-set both the shared secret and the date and time.&lt;/p&gt;

&lt;p&gt;The easiest way to install OktaArduToken onto an actual ArduBoy is to use the &lt;a href="https://www.arduino.cc/en/Main/Software" rel="noopener noreferrer"&gt;Arduino IDE&lt;/a&gt;. This allows you to both edit and upload the source as well as providing the command line tool, &lt;code&gt;avrdude&lt;/code&gt;, to upload binaries.&lt;/p&gt;

&lt;p&gt;Here’s an example install command using &lt;code&gt;avrdude&lt;/code&gt; on Mac:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avrdude -v \
-C /Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf \
-p atmega32u4 \
-c avr109 \
-P /dev/cu.usbmodem1411 \
-U flash:w:&amp;lt;path to OktaArduToken project&amp;gt;/OktaArduToken.hex

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; The &lt;code&gt;-p&lt;/code&gt; parameter specifies the ArduBoy part number and the &lt;code&gt;-c&lt;/code&gt; parameter specifies the ArduBoy programmer type. The &lt;code&gt;-P&lt;/code&gt; parameter will be different on your Mac. You can see the list of available serial ports by using this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -la /dev/cu.*

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’re looking for the entry that contains &lt;code&gt;usbmodem&lt;/code&gt; in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with Source Code and Dependencies
&lt;/h2&gt;

&lt;p&gt;If you want to work with the source code in the Arduino IDE, compile it, and upload it to your ArduBoy, you’ll need to install a few libraries. For each of these, navigate to: &lt;code&gt;Sketch -&amp;gt; Include Library -&amp;gt; Manage Libraries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/MLXXXp/Arduboy2" rel="noopener noreferrer"&gt;Arduboy2&lt;/a&gt; - An alternative library for the Arduboy miniature game system&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.leonardomiliani.com/en/2011/swrtc-un-orologio-in-tempo-reale-via-software/" rel="noopener noreferrer"&gt;swRTC&lt;/a&gt; - A software real-time clock&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lucadentella/TOTP-Arduino" rel="noopener noreferrer"&gt;TOTP-Arduino&lt;/a&gt; - Library to generate time-based one-time Passwords&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NetRat/Base32" rel="noopener noreferrer"&gt;Base32&lt;/a&gt; - a library to encode strings into and decode strings from Base32&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;Base32&lt;/code&gt; library is the only one that you can’t install via the library manager in Arduino IDE. It’s easy enough to install by cloning the GitHub repository to your local Arduino IDE libraries folder. On Mac, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/Documents/Arduino/libraries/
git clone https://github.com/NetRat/Base32.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all your libraries are in place, you can navigate to: &lt;code&gt;File -&amp;gt; Open...&lt;/code&gt; in the Arduino IDE and choose the &lt;code&gt;OktaArduToken.ino&lt;/code&gt; file. You should then be able to navigate to: &lt;code&gt;Sketch -&amp;gt; Verify/Compile&lt;/code&gt; to compile the code. If you get any errors, make sure that all the above libraries are installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating around the OktaArduToken Interface
&lt;/h2&gt;

&lt;p&gt;OktaArduToken is unique among TOTP examples for Arduino or ArduBoy in that it has an interface to set the shared secret and to set the date and time. Most examples require you to hardcode the secret into the source code before uploading.&lt;/p&gt;

&lt;p&gt;With a total of 6 buttons, the interface to set the shared secret and the date and time may remind you of a ’90s era flip phone. ;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the Shared Secret
&lt;/h3&gt;

&lt;p&gt;When you first launch that app, you’ll see the shared secret setting screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fsecret-ba725b8c450eb647a6c3b7816a17ecb28ca5ba5b8cb6f680bc6ceff9b993f104.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fsecret-ba725b8c450eb647a6c3b7816a17ecb28ca5ba5b8cb6f680bc6ceff9b993f104.png" alt="Secret setting screen" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okta Verify uses a 16-byte Base32 encoded string for the shared secret. Initially, this is shown as 16 &lt;code&gt;M&lt;/code&gt;s. You can use the up and down buttons to navigate around the set of capital letters and the numbers from 0 - 9. You can use the left and right buttons to move positions within the available 16 characters.&lt;/p&gt;

&lt;p&gt;The interface automatically wraps. That is, hitting the right button when you’re on the 16th character moves the cursor back to the 1st character. Hitting the left button when you’re on the 1st character moves the cursor to the 16th character. Likewise, hitting the up button when &lt;code&gt;9&lt;/code&gt; is showing, will change that character to &lt;code&gt;A&lt;/code&gt;. Hitting the down arrow when &lt;code&gt;A&lt;/code&gt; is showing, will change that character to &lt;code&gt;9&lt;/code&gt; (it goes &lt;code&gt;A&lt;/code&gt;-&lt;code&gt;Z&lt;/code&gt; and then &lt;code&gt;0&lt;/code&gt;-&lt;code&gt;9&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;When the shared secret is set, press the &lt;code&gt;A&lt;/code&gt; button to move on to the date and time setting screen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; See below for how to configure Okta for MFA and obtain the shared secret to program in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the Date and Time
&lt;/h3&gt;

&lt;p&gt;Once you’ve saved the shared secret, you’ll see the date and time setting screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fdate-37d38a9226b3fe2f22667c05b3cab934e5995cdfaeb451d1c5060595edf761cc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fdate-37d38a9226b3fe2f22667c05b3cab934e5995cdfaeb451d1c5060595edf761cc.png" alt="Time setting screen" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the up and down arrows to change the numbers for each part of the date and time. You can use the right and left buttons to change positions on the date and time interface. The interface will automatically skip over separators and will automatically wrap around in a similar way to the shared secret interface.&lt;/p&gt;

&lt;p&gt;Once the date and time are set, press the &lt;code&gt;A&lt;/code&gt; button to move on to the TOTP screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Precision is important, so it is recommended that you set the time ahead by 10 seconds, watch a clock with a seconds counter and hit the &lt;code&gt;A&lt;/code&gt; button the moment at which the times match. Also, the date and time that you set should always be GMT regardless of your current time zone. Also, There is currently NO error checking of any kind. That is, if you put in an invalid date and/or time, you will get unexpected results.&lt;/p&gt;

&lt;p&gt;You can press the &lt;code&gt;B&lt;/code&gt; button to return to the shared secret screen from here.&lt;/p&gt;

&lt;h3&gt;
  
  
  The TOTP Display
&lt;/h3&gt;

&lt;p&gt;Once the shared secret and date and time are set, you see the TOTP screen. At the top of the screen, in a large font, you see the current passcode. This passcode changes every 30 seconds. Below the passcode, you see the full date and time which updates every second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Ftotp-cfee5c2c2641f86f1e4c15b316df0ba25fe029dd16d5cc470e5d4bdf8e5f39d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Ftotp-cfee5c2c2641f86f1e4c15b316df0ba25fe029dd16d5cc470e5d4bdf8e5f39d3.png" alt="TOTP screen" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press the &lt;code&gt;A&lt;/code&gt; button to return to the set date and time screen. Press the &lt;code&gt;B&lt;/code&gt; button to return to the set shared secret screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Okta for Multi-factor Authentication
&lt;/h2&gt;

&lt;p&gt;In Okta, there are two complimentary pieces to MFA: enrollment and enforcement. An MFA enrollment policy drives the conditions under which a user will be required to enroll in MFA and what configured factors they must enroll in. A Signon Policy can be configured to require a second factor after authentication. That’s the MFA enforcement part of the policy.&lt;/p&gt;

&lt;p&gt;To get started, signup for a free Okta Developer org at &lt;a href="https://developer.okta.com/signup/" rel="noopener noreferrer"&gt;https://developer.okta.com/signup/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup an Okta group and a new user to make testing the MFA policies easier.&lt;/p&gt;

&lt;p&gt;Log into the admin console of your Okta org. Switch from the &lt;em&gt;Developer Console&lt;/em&gt; to the &lt;em&gt;Classic UI&lt;/em&gt; by selecting the dropdown in the upper left:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fclassicui-b038239766d5cbce947c5ecbb08a52ca1ab973ccfe4d958ead327c93945907b8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fclassicui-b038239766d5cbce947c5ecbb08a52ca1ab973ccfe4d958ead327c93945907b8.png" alt="Classic UI" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, choose: &lt;strong&gt;Directory&lt;/strong&gt; &amp;gt; &lt;strong&gt;Groups&lt;/strong&gt; from the top menu of the admin console. Click &lt;strong&gt;Add Group&lt;/strong&gt; and enter &lt;code&gt;mfaers&lt;/code&gt; for the &lt;em&gt;Name&lt;/em&gt; field. Click &lt;strong&gt;Add Group&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Choose: &lt;strong&gt;Directory&lt;/strong&gt; &amp;gt; &lt;strong&gt;People&lt;/strong&gt; from the top menu of the admin console. Click &lt;strong&gt;Add Person&lt;/strong&gt; and fill in the fields as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;field&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First name&lt;/td&gt;
&lt;td&gt;Jane&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Last name&lt;/td&gt;
&lt;td&gt;Doe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Username&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:jane.doe@mfaers.com"&gt;jane.doe@mfaers.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;primary email&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:jane.doe@mfaers.com"&gt;jane.doe@mfaers.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Groups&lt;/td&gt;
&lt;td&gt;mfaers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password&lt;/td&gt;
&lt;td&gt;Set by admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User must change password on first login&lt;/td&gt;
&lt;td&gt;(unchecked)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Enter a password of your choice. Click &lt;em&gt;Save&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fjanedoe-85b15f78ca1f6504a43edcec57c4bf3a3ba3786de9f190c3980af7318b764fc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fjanedoe-85b15f78ca1f6504a43edcec57c4bf3a3ba3786de9f190c3980af7318b764fc0.png" alt="Jane Doe" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure an MFA Enrollment Policy
&lt;/h3&gt;

&lt;p&gt;Select &lt;strong&gt;Security&lt;/strong&gt; &amp;gt; &lt;strong&gt;Multifactor&lt;/strong&gt; from the top menu of the admin console.&lt;/p&gt;

&lt;p&gt;On the Factor Types tab, select &lt;strong&gt;Active&lt;/strong&gt; next to &lt;em&gt;Okta Verify&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Select the &lt;strong&gt;Factor Enrollment&lt;/strong&gt; tab. Click &lt;strong&gt;Add Multifactor Policy&lt;/strong&gt; , enter &lt;code&gt;mfaers policy&lt;/code&gt; for &lt;em&gt;Policy name&lt;/em&gt; and choose &lt;code&gt;mfaers&lt;/code&gt; for &lt;em&gt;Assign to groups&lt;/em&gt;. Select &lt;strong&gt;required&lt;/strong&gt; from the dropdown next to &lt;em&gt;Okta Verify&lt;/em&gt;. Click &lt;strong&gt;Create Policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerspolicy-851a75057f85b6ced3d8d4165cf751df0919ea1a1d11d703acf945c68abef75a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerspolicy-851a75057f85b6ced3d8d4165cf751df0919ea1a1d11d703acf945c68abef75a.png" alt="MFAers Policy" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Add Rule&lt;/em&gt; dialog, enter &lt;code&gt;mfaers rule&lt;/code&gt; for &lt;em&gt;Rule name&lt;/em&gt; and select &lt;em&gt;the first time a user signs in&lt;/em&gt; in the dropdown next to &lt;em&gt;Enroll in multi-factor&lt;/em&gt;. Click &lt;strong&gt;Create Rule&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaersrule-e1bf363fd76e4283e9017b6f26d36154b462e74840ac8ad181e1ece243e2774c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaersrule-e1bf363fd76e4283e9017b6f26d36154b462e74840ac8ad181e1ece243e2774c.png" alt="MFAers Rule" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s all that’s needed to configure MFA enrollment!&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure an MFA Enforcement Policy
&lt;/h3&gt;

&lt;p&gt;Select &lt;strong&gt;Security&lt;/strong&gt; &amp;gt; &lt;strong&gt;Authentication&lt;/strong&gt; from the top menu of the admin console. Click &lt;strong&gt;Sign On&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add New Okta Sign-on Policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;mfaers policy&lt;/code&gt; in &lt;em&gt;Policy Name&lt;/em&gt; and choose &lt;code&gt;mfaers&lt;/code&gt; in &lt;em&gt;Assign to Groups&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Create Policy and Add Rule&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerssignonpolicy-68924aa72c45aa16de5e7bbd1fa49a5fe265c95a8b2a39a3f91f000009028260.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerssignonpolicy-68924aa72c45aa16de5e7bbd1fa49a5fe265c95a8b2a39a3f91f000009028260.png" alt="MFAers Sign-on Policy" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;mfaers rule&lt;/code&gt; for &lt;em&gt;Rule Name&lt;/em&gt; and check &lt;em&gt;Prompt for Factor&lt;/em&gt;. Select &lt;strong&gt;Every Time&lt;/strong&gt; &amp;gt; &lt;strong&gt;Create Rule&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerssignonrule-d5a07d06be58ac5e74d5762d636f19afe8fc01424f4824bd3f714511c01e3ae0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fmfaerssignonrule-d5a07d06be58ac5e74d5762d636f19afe8fc01424f4824bd3f714511c01e3ae0.png" alt="MFAers Sign-on Rule" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s all that’s needed to configure MFA enforcement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authenticate with Okta and the OktaArduToken
&lt;/h2&gt;

&lt;p&gt;In a private browsing window, navigate to your okta org and login as &lt;a href="mailto:jane.doe@mfaers.com"&gt;jane.doe@mfaers.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should see a screen to setup Okta Verify. Click &lt;strong&gt;Configure factor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fconfigurefactor-8e04f4be9537ec01f29cb56853a9789b27d184ef70fc245ea5affc50df62daaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fconfigurefactor-8e04f4be9537ec01f29cb56853a9789b27d184ef70fc245ea5affc50df62daaa.png" alt="Configure factor" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen select any device type (it doesn’t matter since we’ll be setting up our ArduBoy anyway). Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On the Setup Okta Verify screen, click &lt;strong&gt;Can’t scan?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fcantscan-958b83f5503840b33954b166fa68d42cbab33cd819c9fd755abc7adcafb2ae1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fcantscan-958b83f5503840b33954b166fa68d42cbab33cd819c9fd755abc7adcafb2ae1b.png" alt="Can't scan?" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll then see the Secret Key Field. Turn on your ArduBoy (or use ProjectABE) and enter the shared secret value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fsharedsecret-f42786960f630dc41c448a73e42f8eb34c405ec6359f62284bb8f81664b05f40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.okta.com%2Fassets%2Fblog%2Fardu-token-mfa%2Fsharedsecret-f42786960f630dc41c448a73e42f8eb34c405ec6359f62284bb8f81664b05f40.png" alt="Shared secret" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Arduboy, press the &lt;code&gt;A&lt;/code&gt; button and enter in the correct date and time (GMT timezone). Press the &lt;code&gt;A&lt;/code&gt; button. This will bring you to the TOTP screen.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Next&lt;/strong&gt; on the Setup Okta Verify dialog. Enter in the code displayed on the ArduBoy and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If all goes well, you’ll see a screen asking for you to set a security question and answer to finish configuring your account.&lt;/p&gt;

&lt;p&gt;You’ve now completed enrollment in Okta Verify using an ArduBoy as a hardware token! Pretty cool stuff.&lt;/p&gt;

&lt;p&gt;You could logout and login again and you will be prompted to put in a code again which you would get from the ArduBoy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The clock component in ProjectABE is not very accurate and will get behind or ahead very quickly. You can always press the &lt;code&gt;A&lt;/code&gt; button to set the time once again so that the passcode shown is correct.&lt;/p&gt;

&lt;p&gt;You can also program in the value in the actual Okta Verify app on your mobile device and confirm that the passcode shown is the same as the passcode on the ArduBoy.&lt;/p&gt;

&lt;p&gt;Here’s the OktaArduToken side-by-side with the Okta Verify mobile app:&lt;/p&gt;



&lt;h2&gt;
  
  
  A look at the TOTP Arduino Code
&lt;/h2&gt;

&lt;p&gt;The code for OktaArduToken is in a single sketch file: &lt;code&gt;OktaArduToken.ino&lt;/code&gt;. I am sure this is not best practice and would benefit from some C++ objectification, but it works for a quick little hobby project.&lt;/p&gt;

&lt;p&gt;It all boils down to three lines of code in the &lt;code&gt;ShowTotpCode()&lt;/code&gt; method, thanks to the TOTP and swRTC libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TOTP totp = TOTP(hmacKey, 10);
long GMT = rtc.getTimestamp();
totpCode = totp.getCode(GMT);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses the &lt;code&gt;hmacKey&lt;/code&gt;, which is the Base32 decoded value of the shared secret along with the current timestamp to compute the current totpCode. It is this 6-digit code that is displayed on the ArduBoy screen.&lt;/p&gt;

&lt;p&gt;The other key enabling feature is the ability to write the shared secret and current time to EEPROM and to read those values back out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void writeTotpInfo(TotpInfo totpInfo) {
  writeString(TOTP_SECRET_SAVE_ADDRESS, totpInfo.secret);
  writeInt(TOTP_SEC_SAVE_ADDRESS, totpInfo.sec);
  writeInt(TOTP_MIN_SAVE_ADDRESS, totpInfo.minu);
  writeInt(TOTP_HOUR_SAVE_ADDRESS, totpInfo.hour);
  writeInt(TOTP_DAY_SAVE_ADDRESS, totpInfo.day);
  writeInt(TOTP_MON_SAVE_ADDRESS, totpInfo.mon);
  writeInt(TOTP_YEAR_SAVE_ADDRESS, totpInfo.year);
  DEBUG_PRINTLN("Wrote totpInfo to eeprom.");
}

TotpInfo readTotpInfo() {
  TotpInfo ret = {};

  ret.secret = readString(TOTP_SECRET_SAVE_ADDRESS, 16);
  ret.sec = readInt(TOTP_SEC_SAVE_ADDRESS);
  ret.minu = readInt(TOTP_MIN_SAVE_ADDRESS);
  ret.hour = readInt(TOTP_HOUR_SAVE_ADDRESS);
  ret.day = readInt(TOTP_DAY_SAVE_ADDRESS);
  ret.mon = readInt(TOTP_MON_SAVE_ADDRESS);
  ret.year = readInt(TOTP_YEAR_SAVE_ADDRESS);

  return ret;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s a bunch of supporting methods to handle the input interfaces for the shared secret and date and time as well as displaying things in the right spot on the display.&lt;/p&gt;

&lt;p&gt;Being a bit of a n00b to Arduino program, I am sure this code could be improved on. &lt;a href="https://github.com/oktadeveloper/okta-ardu-token-example" rel="noopener noreferrer"&gt;I &amp;lt;3 pull requests&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More About Okta Verify and Multi-factor Authentication
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed seeing how authentication with MFA using Okta Verify works along with alternate token devices. The requirements for creating your own token are a programmable microprocessor with a clock and a display&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about MFA with Okta, check out these posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/05/16/multifactor-authentication-4-challenges-faced-by-developers" rel="noopener noreferrer"&gt;MFA: 4 challenges faced by developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/06/12/mfa-in-spring-boot" rel="noopener noreferrer"&gt;Secure Your Spring Boot Application with Multi-Factor Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/06/22/multi-factor-authentication-command-line" rel="noopener noreferrer"&gt;Use Multi-factor from the Command Line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/05/22/simple-multifactor-authentication-in-node" rel="noopener noreferrer"&gt;Simple Multi-factor authentication in Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.okta.com/blog/2018/02/08/set-up-and-enforce-multi-factor-auth-with-okta" rel="noopener noreferrer"&gt;Set Up and Enforce MFA with the Okta API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, please &lt;a href="https://twitter.com/OktaDev" rel="noopener noreferrer"&gt;follow us on Twitter&lt;/a&gt; to find more great resources like this, request other topics for us to write about, and follow along with our new open source libraries and projects!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; : If you liked this project and want to see the source code in one place, please go checkout and star its &lt;a href="https://github.com/oktadeveloper/okta-ardu-token-example" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And… If you have any questions, please leave a comment below!&lt;/p&gt;

</description>
      <category>security</category>
      <category>mfa</category>
      <category>arduino</category>
    </item>
  </channel>
</rss>
