{"id":55046,"date":"2016-04-19T07:00:57","date_gmt":"2016-04-19T04:00:57","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=55046"},"modified":"2016-04-17T16:54:26","modified_gmt":"2016-04-17T13:54:26","slug":"spring-oauth2-jwt-sample","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html","title":{"rendered":"Spring Oauth2 with JWT Sample"},"content":{"rendered":"<p>Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular use case of setting up Oauth2 authentication for a Spring Boot application. In this example, we will JSON Web Token (JWT) as the format of the Oauth2 token.<\/p>\n<p>This sample was developed partly based on the <a href=\"https:\/\/github.com\/spring-projects\/spring-security-oauth\/tree\/master\/samples\/oauth2\">official sample<\/a>\u00a0of Spring Security Oauth 2. However, we will focus on understanding the principal of the Oauth 2 request.<\/p>\n<p>The source code is at\u00a0<a href=\"https:\/\/github.com\/tuanngda\/spring-boot-oauth2-demo.git\">https:\/\/github.com\/tuanngda\/spring-boot-oauth2-demo.git<\/a><\/p>\n<h2>Background<\/h2>\n<h4>Oauth2 and JWT<\/h4>\n<p>We will not go to detail when you want to use Oauth2 and JWT. In general, you may want to adopt Oauth if you need to allow other people to build front end app for you services. We focus on Oauth2 and JWT because they are the most popular authentication framework and protocol in the market.<\/p>\n<h4>Spring Security Oauth 2<\/h4>\n<p>Spring Security Oauth2 is an implementation of Oauth 2 that built on top of Spring Security, which is a very extensible authentication framework.<\/p>\n<p>In overall, Spring Security includes 2 basic steps, creating an authentication object for each request and applying authorization check depending on authentication. The first step was done in a multi layer Security Filter. Depending on the configuration, each layer can help to create authentication for basic authentication, digest authentication, form authentication or any custom authentication that we choose to implement ourselves. The client side session we built in previous article is one custom authentication and Spring Security Oauth 2 is another custom authentication.<\/p>\n<p>Because in this example, our application both provides and consume token, Spring Security Oauth 2 should not be the sole authentication layer for the application. We need another authentication mechanism to protect the token provider endpoint.<\/p>\n<p>For a cluster environment, the token or the secret to sign token (for JWT) suppose to be persisted but we skip this step to simplify the example. Similarly, the user authentication and client identities are all hard-coded.<\/p>\n<h2>System Design<\/h2>\n<h4>Overview<\/h4>\n<p>In our application, we need to setup 3 components<\/p>\n<ul>\n<li>Authorization Endpoint and Token Endpoint to help providing Oauth 2 token.<\/li>\n<li>A\u00a0WebSecurityConfigurerAdapter, which is an authentication layer with hard-coded order of 3 (according to <a href=\"https:\/\/spring.io\/team\/dsyer\">Dave Syer<\/a>). This authentication layer will setup authentication and principal for any request that contains Oauth 2 token.<\/li>\n<li>Another authentication mechanism to protect Token endpoint and other resources if the token is missing. In this sample, we choose basic authentication for its simplicity when writing tests. As we do not specify the order, it will take default value of 100. With Spring security, the lower order, the higher priority; so we should expect Oauth 2 come before basic authentication in the FilterChainProxy. Inspecting in IDE prove that our setup is correct.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/04\/FilterChain.png\" rel=\"attachment wp-att-55072\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-55072\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/04\/FilterChain.png\" alt=\"FilterChain\" width=\"413\" height=\"295\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/04\/FilterChain.png 413w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/04\/FilterChain-300x214.png 300w\" sizes=\"(max-width: 413px) 100vw, 413px\" \/><\/a><\/p>\n<p>In the above picture, Oauth2AuthenticationProcessingFilter appear in front of BasicAuthenticationFilter.<\/p>\n<h4>Authorization Server Configuration<\/h4>\n<p>Here is our config for Authorization and Token Endpoint<\/p>\n<pre class=\" brush:java\">@Configuration\r\n@EnableAuthorizationServer\r\npublic class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {\r\n\r\n    @Value(\"${resource.id:spring-boot-application}\")\r\n    private String resourceId;\r\n    \r\n    @Value(\"${access_token.validity_period:3600}\")\r\n    int accessTokenValiditySeconds = 3600;\r\n\r\n    @Autowired\r\n    private AuthenticationManager authenticationManager;\r\n    \r\n    @Bean\r\n    public JwtAccessTokenConverter accessTokenConverter() {\r\n        return new JwtAccessTokenConverter();\r\n    }\r\n\r\n    @Override\r\n    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {\r\n        endpoints\r\n            .authenticationManager(this.authenticationManager)\r\n            .accessTokenConverter(accessTokenConverter());\r\n    }\r\n    \r\n    @Override\r\n    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {\r\n        oauthServer.tokenKeyAccess(\"isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')\")\r\n            .checkTokenAccess(\"hasAuthority('ROLE_TRUSTED_CLIENT')\");\r\n    }\r\n\r\n    @Override\r\n    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {\r\n        clients.inMemory()\r\n            .withClient(\"normal-app\")\r\n                .authorizedGrantTypes(\"authorization_code\", \"implicit\")\r\n                .authorities(\"ROLE_CLIENT\")\r\n                .scopes(\"read\", \"write\")\r\n                .resourceIds(resourceId)\r\n                .accessTokenValiditySeconds(accessTokenValiditySeconds)\r\n        .and()\r\n            .withClient(\"trusted-app\")\r\n                .authorizedGrantTypes(\"client_credentials\", \"password\")\r\n                .authorities(\"ROLE_TRUSTED_CLIENT\")\r\n                .scopes(\"read\", \"write\")\r\n                .resourceIds(resourceId)\r\n                .accessTokenValiditySeconds(accessTokenValiditySeconds)\r\n                .secret(\"secret\");\r\n    }\r\n}<\/pre>\n<p>There are few things worth noticing about this implementation.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<ul>\n<li>Setting up JWT token is as simple as using JwtAccessTokenConverter. Because we never setup the signing key, it is randomly generated. If we intended to deploy our application to cloud, it is a must to sync the signing key across all authorization servers.<\/li>\n<li>Instead of creating authentication manager, we choose to inject an existing authentication manager from Spring container. With this step, we can share the authentication manager with the Basic Authentication filter.<\/li>\n<li>It is possible to have trusted application and not trusted application. Trusted application can have their own secret. This is necessary for client credential authorization grant. Except client credentials, all 3 other grants require resource owner&#8217;s credential.<\/li>\n<li>We allow anonymous for checking token endpoint. With this configuration, the checking token is accessible without basic authentication or Oauth 2 token.<\/li>\n<\/ul>\n<h4>Resource Server Configuration<\/h4>\n<p>Here is our configuration for Resource Server Configuration<\/p>\n<pre class=\" brush:java\">@Configuration\r\n@EnableResourceServer\r\npublic class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {\r\n    \r\n    @Value(\"${resource.id:spring-boot-application}\")\r\n    private String resourceId;\r\n    \r\n    @Override\r\n    public void configure(ResourceServerSecurityConfigurer resources) {\r\n        resources.resourceId(resourceId);\r\n    }\r\n\r\n    @Override\r\n    public void configure(HttpSecurity http) throws Exception {\r\n         http.requestMatcher(new OAuthRequestedMatcher())\r\n                .authorizeRequests()\r\n                 .antMatchers(HttpMethod.OPTIONS).permitAll()\r\n                    .anyRequest().authenticated();\r\n    }\r\n    \r\n    private static class OAuthRequestedMatcher implements RequestMatcher {\r\n        public boolean matches(HttpServletRequest request) {\r\n            String auth = request.getHeader(\"Authorization\");\r\n            \/\/ Determine if the client request contained an OAuth Authorization\r\n            boolean haveOauth2Token = (auth != null) &amp;&amp; auth.startsWith(\"Bearer\");\r\n            boolean haveAccessToken = request.getParameter(\"access_token\")!=null;\r\n   return haveOauth2Token || haveAccessToken;\r\n        }\r\n    }\r\n\r\n}<\/pre>\n<p>Here are few things to take note:<\/p>\n<ul>\n<li>The\u00a0OAuthRequestedMatcher is added in so that the Oauth filter will only process Oauth2 requests. We added this in so that an unauthorized request will be denied at the Basic Authentication layer instead of Oauth 2 layer. This may not make any difference in term of functionality but we added it in for usability. For the client, they will received 401 HTTP Status with this new header versus the old header:\n<ul>\n<li><i>WWW-Authenticate:Basic realm=&#8221;Realm&#8221;<\/i><\/li>\n<li><i>WWW-Authenticate:Bearer realm=&#8221;spring-boot-application&#8221;, error=&#8221;unauthorized&#8221;, error_description=&#8221;Full authentication is required to access this resource&#8221;<\/i><\/li>\n<\/ul>\n<\/li>\n<li>With the new response header, a browser will auto\u00a0prompt user\u00a0for username, password. If you do not want the resource to be accessible by any other authentication mechanism, this step is not necessary.<\/li>\n<li>Some browsers like Chrome like to send OPTIONS request to look for CORS before making AJAX call. Therefore, it is better to \u00a0always allow OPTIONS requests.<\/li>\n<\/ul>\n<h4>Basic Authentication Security Configuration<\/h4>\n<p>As mentioned earlier, because we need to protect the token provider endpoint.<\/p>\n<pre class=\"brush:java; wrap-lines:false\">@Configuration\r\n@EnableGlobalMethodSecurity(prePostEnabled = true)\r\n@EnableWebSecurity\r\npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {\r\n    \r\n    @Autowired\r\n    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {\r\n        auth.inMemoryAuthentication().withUser(\"user\").password(\"password\").roles(\"USER\").and().withUser(\"admin\")\r\n                .password(\"password\").roles(\"USER\", \"ADMIN\");\r\n    }\r\n    \r\n    @Override\r\n    protected void configure(HttpSecurity http) throws Exception {\r\n     http\r\n        .authorizeRequests()\r\n            .antMatchers(HttpMethod.OPTIONS).permitAll()\r\n            .anyRequest().authenticated()\r\n            .and().httpBasic()\r\n            .and().csrf().disable();\r\n    }\r\n    \r\n    @Override\r\n    @Bean\r\n    public AuthenticationManager authenticationManagerBean() throws Exception {\r\n        return super.authenticationManagerBean();\r\n    }\r\n}<\/pre>\n<p>There are few things to take note:<\/p>\n<ul>\n<li>We expose the AuthenticationManager bean so that our two authentication security adapter can share a single authentication manager.<\/li>\n<li>Spring Security CSRF working seamlessly with JSP but is a hassle for RestAPI. Because we want this sample app to be used as a base for users to develop their own application, we turned CSRF off and add in a CORS filter so that it can be use right away.<\/li>\n<\/ul>\n<h2>Testing<\/h2>\n<p>We wrote one test scenario for each authorization grant type following exactly Oauth2 specifications. Because Spring Security Oauth 2 is an implementation based on Spring Security framework, our interest is veered toward seeing how the underlying authentication and principal are constructed.<\/p>\n<p>Before summarizing the outcome of experiment, let take a quick look at somethings to take notes.<\/p>\n<ul>\n<li>Most of the requests to token provider endpoints were sent using POST requests but they include user credential as parameters. Even though we put this credential as part of url for convenient, never do this in your Oauth 2 client.<\/li>\n<li>We created 2 endpoints\u00a0<i>\/resources\/principal<\/i> and\u00a0<i>\/resources\/roles<\/i> to capture the principal and authority for Oauth 2 authentication.<\/li>\n<\/ul>\n<p>Here is our setup:<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"72\"><strong>User<\/strong><\/td>\n<td width=\"184\"><strong>Type<\/strong><\/td>\n<td width=\"187\"><strong>Authorities<\/strong><\/td>\n<td width=\"65\"><strong>Credential<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"72\">user<\/td>\n<td width=\"184\">resource owner<\/td>\n<td width=\"187\">ROLE_USER<\/td>\n<td width=\"65\">Y<\/td>\n<\/tr>\n<tr>\n<td width=\"72\">admin<\/td>\n<td width=\"184\">resource owner<\/td>\n<td width=\"187\">ROLE_ADMIN<\/td>\n<td width=\"65\">Y<\/td>\n<\/tr>\n<tr>\n<td width=\"72\">normal-app<\/td>\n<td width=\"184\">client<\/td>\n<td width=\"187\">ROLE_CLIENT<\/td>\n<td width=\"65\">N<\/td>\n<\/tr>\n<tr>\n<td width=\"72\">trusted-app<\/td>\n<td width=\"184\">client<\/td>\n<td width=\"187\">ROLE_TRUSTED_CLIENT<\/td>\n<td width=\"65\">Y<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"255\"><strong>Grant Type<\/strong><\/td>\n<td width=\"95\"><strong>User<\/strong><\/td>\n<td width=\"84\"><strong>Client<\/strong><\/td>\n<td width=\"91\"><strong>Principal<\/strong><\/td>\n<td width=\"107\"><strong>Authorities<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"255\">Authorization Code<\/td>\n<td width=\"95\">user<\/td>\n<td width=\"84\">normal-app<\/td>\n<td width=\"91\">user<\/td>\n<td width=\"107\">ROLE_USER<\/td>\n<\/tr>\n<tr>\n<td width=\"255\">Client Credentials<\/td>\n<td width=\"95\">NA<\/td>\n<td width=\"84\">trusted-app<\/td>\n<td width=\"91\">trusted-app<\/td>\n<td width=\"107\">No Authority<\/td>\n<\/tr>\n<tr>\n<td width=\"255\">Implicit<\/td>\n<td width=\"95\">user<\/td>\n<td width=\"84\">normal-app<\/td>\n<td width=\"91\">user<\/td>\n<td width=\"107\">ROLE_USER<\/td>\n<\/tr>\n<tr>\n<td width=\"255\">Resource Owner Password Credentials<\/td>\n<td width=\"95\">user<\/td>\n<td width=\"84\">trusted-app<\/td>\n<td width=\"91\">user<\/td>\n<td width=\"107\">ROLE_USER<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"line-height: 1.5;\">This result is pretty as expected except for Client Credentials. Interestingly, even though the client retrieve Oauth 2 token by client credential, the approved request still does not have any of client authorities but only client credential. I think this make sense because the token from Implicit Grant Type cannot be reused.<\/span>Here is what we find out<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/sgdev-blog.blogspot.com\/2016\/04\/spring-oauth2-with-jwt-sample.html\">Spring Oauth2 with JWT Sample<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/join-us\/jcg\/\">JCG partner<\/a> Nguyen Anh Tuan at the <a href=\"http:\/\/sgdev-blog.blogspot.com\/\">Developers Corner<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular use case of setting up Oauth2 authentication for a Spring Boot application. In this example, we will JSON Web Token (JWT) as the format of the Oauth2 token. This sample was developed partly &hellip;<\/p>\n","protected":false},"author":558,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[1289,30],"class_list":["post-55046","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-jwt","tag-spring"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Oauth2 with JWT Sample - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular\" \/>\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\/2016\/04\/spring-oauth2-jwt-sample.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Oauth2 with JWT Sample - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.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=\"2016-04-19T04:00:57+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=\"Lim Han\" \/>\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=\"Lim Han\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html\"},\"author\":{\"name\":\"Lim Han\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/dd250541a89aea5441c1821cb3760296\"},\"headline\":\"Spring Oauth2 with JWT Sample\",\"datePublished\":\"2016-04-19T04:00:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html\"},\"wordCount\":1130,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"JWT\",\"Spring\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html\",\"name\":\"Spring Oauth2 with JWT Sample - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2016-04-19T04:00:57+00:00\",\"description\":\"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.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\\\/2016\\\/04\\\/spring-oauth2-jwt-sample.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\":\"Spring Oauth2 with JWT Sample\"}]},{\"@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\\\/dd250541a89aea5441c1821cb3760296\",\"name\":\"Lim Han\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g\",\"caption\":\"Lim Han\"},\"sameAs\":[\"http:\\\/\\\/sgdev-blog.blogspot.gr\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/lim-han\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Oauth2 with JWT Sample - Java Code Geeks","description":"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular","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\/2016\/04\/spring-oauth2-jwt-sample.html","og_locale":"en_US","og_type":"article","og_title":"Spring Oauth2 with JWT Sample - Java Code Geeks","og_description":"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular","og_url":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2016-04-19T04:00:57+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":"Lim Han","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Lim Han","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html"},"author":{"name":"Lim Han","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/dd250541a89aea5441c1821cb3760296"},"headline":"Spring Oauth2 with JWT Sample","datePublished":"2016-04-19T04:00:57+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html"},"wordCount":1130,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["JWT","Spring"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html","url":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html","name":"Spring Oauth2 with JWT Sample - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2016-04-19T04:00:57+00:00","description":"Sometimes ago, we published one article sharing a custom approach to implement stateless session in cloud environment. Today, let explore another popular","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2016\/04\/spring-oauth2-jwt-sample.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\/2016\/04\/spring-oauth2-jwt-sample.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":"Spring Oauth2 with JWT Sample"}]},{"@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\/dd250541a89aea5441c1821cb3760296","name":"Lim Han","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d76eb9e52e6bb2ddbcf5f3bd69748e6161df0075743b4feacbed81715f4c5447?s=96&d=mm&r=g","caption":"Lim Han"},"sameAs":["http:\/\/sgdev-blog.blogspot.gr\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/lim-han"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/55046","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\/558"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=55046"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/55046\/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=55046"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=55046"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=55046"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}