In the previous tutorial, I showed you how to implement an Authorization Server using Spring Authorization Server, but the information about RegisteredClient in this tutorial is stored in memory. To store RegisteredClient information in the database, how will we do it? In this tutorial, I will show you how to do this!
First, I also created a new Spring Boot project with Spring Web Starter, Spring Security Starter, Spring Data JPA, PostgreSQL Driver and OAuth2 Authorization Server Starter::
for example.
Result:
I will configure Spring Security as in the tutorial Implement OAuth Authorization Server using Spring Authorization Server as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package com.huongdanjava.springauthorizationserver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SpringSecurityConfiguration { @Bean SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { // @formatter:off http .authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated() ) .formLogin(Customizer.withDefaults()); // @formatter:on return http.build(); } @Bean public UserDetailsService users() { // @formatter:off UserDetails user = User.withDefaultPasswordEncoder() .username("admin") .password("password") .roles("ADMIN").build(); // @formatter:on return new InMemoryUserDetailsManager(user); } } |
As for the configuration for the Authorization Server, I also do the same as the tutorial Implement OAuth Authorization Server using Spring Authorization Server, but I will declare the RegisteredClient information later:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
package com.huongdanjava.springauthorizationserver; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.UUID; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; import org.springframework.security.web.SecurityFilterChain; import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.proc.SecurityContext; @Configuration public class AuthorizationServerConfiguration { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); return http.formLogin(Customizer.withDefaults()).build(); } @Bean public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } @Bean public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException { RSAKey rsaKey = generateRsa(); JWKSet jwkSet = new JWKSet(rsaKey); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); } private static RSAKey generateRsa() throws NoSuchAlgorithmException { KeyPair keyPair = generateRsaKey(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // @formatter:off return new RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build(); // @formatter:on } private static KeyPair generateRsaKey() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); return keyPairGenerator.generateKeyPair(); } } |
To store RegisteredClient information in the database, first, we need to define the database structure to do this.
By default, Spring Authorization Server provides us with database scripts to create the database structure. You can copy them in the Spring Authorization Server .jar file:
You can go to the Github of the Spring Authorization Server here to copy these files.
I will use Flyway to manage database migration:
1 2 3 4 |
<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency> |
by copying the schema files of the Spring Authorization Server into the src/main/resources/db/migration directory as follows:
In the script that creates the oauth2_authorization table in the file V1__oauth2-authorization-schema.sql, there is a definition of the BLOB data type, presumably for the Oracle database:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
CREATE TABLE oauth2_authorization ( id varchar(100) NOT NULL, registered_client_id varchar(100) NOT NULL, principal_name varchar(200) NOT NULL, authorization_grant_type varchar(100) NOT NULL, authorized_scopes varchar(1000) DEFAULT NULL, attributes blob DEFAULT NULL, state varchar(500) DEFAULT NULL, authorization_code_value blob DEFAULT NULL, authorization_code_issued_at timestamp DEFAULT NULL, authorization_code_expires_at timestamp DEFAULT NULL, authorization_code_metadata blob DEFAULT NULL, access_token_value blob DEFAULT NULL, access_token_issued_at timestamp DEFAULT NULL, access_token_expires_at timestamp DEFAULT NULL, access_token_metadata blob DEFAULT NULL, access_token_type varchar(100) DEFAULT NULL, access_token_scopes varchar(1000) DEFAULT NULL, oidc_id_token_value blob DEFAULT NULL, oidc_id_token_issued_at timestamp DEFAULT NULL, oidc_id_token_expires_at timestamp DEFAULT NULL, oidc_id_token_metadata blob DEFAULT NULL, refresh_token_value blob DEFAULT NULL, refresh_token_issued_at timestamp DEFAULT NULL, refresh_token_expires_at timestamp DEFAULT NULL, refresh_token_metadata blob DEFAULT NULL, user_code_value blob DEFAULT NULL, user_code_issued_at timestamp DEFAULT NULL, user_code_expires_at timestamp DEFAULT NULL, user_code_metadata blob DEFAULT NULL, device_code_value blob DEFAULT NULL, device_code_issued_at timestamp DEFAULT NULL, device_code_expires_at timestamp DEFAULT NULL, device_code_metadata blob DEFAULT NULL, PRIMARY KEY (id) ); |
If you are using a PostgreSQL database like me, you need to change to TEXT type! Otherwise, running the database migration will fail.
Declare the Datasource to run the database migration as follows:
1 2 3 |
spring.datasource.url=jdbc:postgresql://localhost:5432/authorization_server spring.datasource.username=khanh spring.datasource.password=1 |
Now you can define RegisteredClient in the database, for example as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Bean public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) { // @formatter:off RegisteredClient registeredClient = RegisteredClient.withId("e4a295f7-0a5f-4cbc-bcd3-d870243d1b05") .clientId("huongdanjava1") .clientSecret("{noop}123") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .build(); // @formatter:on JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate); registeredClientRepository.save(registeredClient); return registeredClientRepository; } |
Here, I define a RegisteredClient with a grant type of client_credentials with a fixed ID so that every time I start the app, there is no duplicate record in the database. Depending on your needs, please write the corresponding code!
We will use the JdbcRegisteredClientRepository object to store this RegisteredClient information. The parameter when initializing the JdbcRegisteredClientRepository object is the JdbcTemplate object.
Now, if you run the application, you will see in the oauth2_registered_client table, a new record of RegisteredClient that I declared above, is inserted:
That’s it guys, if you now run the application and get the clientId token above, you will see the following results:
Binod
i got invalid_client why i have checked all also use passwordEncoder too but still getting invalid client error why how can i fix it
mohsen
hi i need to store token in mongodb and retrive from this database can you help me
Khanh Nguyen
Did you try to implement it using Spring Data MongoDB?
Alex D
Can the registeredclient db schema be customized? I dont want the json data as it is not maintainable in production
Antonio
Hello, I have a question about the relationship between registeredclient and users. Can we have the same registeredClient for multiple users? There is also a principalName in the table, this will change according the user login. So how can we have one registeredclient for multiple logged user?
Thank you in advance.
Khanh Nguyen
For your first question, I can say yes. For one RegisteredClient, as a Client Application, we can use it for multiple logged users.
Where is the principalName column in the table? Can you please let me know?
Thirumal
I am getting the following error, can you help me with this? and in database client_setting column, it stores
{"@class":"java.util.Collections$UnmodifiableMap","settings.client.require-proof-key":false,"settings.client.require-authorization-consent":false}
java.lang.ClassNotFoundException: org.springframework.security.cas.jackson2.CasJackson2Module
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:488) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:467) ~[na:na]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:284) ~[spring-core-5.3.22.jar:5.3.22]
at org.springframework.security.jackson2.SecurityJackson2Modules.loadAndGetInstance(SecurityJackson2Modules.java:107) ~[spring-security-core-5.7.3.jar:5.7.3]
at org.springframework.security.jackson2.SecurityJackson2Modules.addToModulesList(SecurityJackson2Modules.java:152) ~[spring-security-core-5.7.3.jar:5.7.3]
at org.springframework.security.jackson2.SecurityJackson2Modules.getModules(SecurityJackson2Modules.java:126) ~[spring-security-core-5.7.3.jar:5.7.3]
at org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository$RegisteredClientParametersMapper.(JdbcRegisteredClientRepository.java:304) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.(JdbcRegisteredClientRepository.java:116) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at in.thirumal.config.AuthorizationServerConfig.registeredClientRepository(AuthorizationServerConfig.java:71) ~[classes/:na]
at in.thirumal.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$4a833596.CGLIB$registeredClientRepository$0() ~[classes/:na]
at in.thirumal.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$4a833596$$FastClassBySpringCGLIB$$a903bd09.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.22.jar:5.3.22]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.22.jar:5.3.22]
at in.thirumal.config.AuthorizationServerConfig$$EnhancerBySpringCGLIB$$4a833596.registeredClientRepository() ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:233) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1284) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1245) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2ConfigurerUtils.getBean(OAuth2ConfigurerUtils.java:184) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2ConfigurerUtils.getRegisteredClientRepository(OAuth2ConfigurerUtils.java:62) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2ClientAuthenticationConfigurer.createDefaultAuthenticationProviders(OAuth2ClientAuthenticationConfigurer.java:165) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2ClientAuthenticationConfigurer.init(OAuth2ClientAuthenticationConfigurer.java:135) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer.lambda$init$1(OAuth2AuthorizationServerConfigurer.java:228) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647) ~[na:na]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer.init(OAuth2AuthorizationServerConfigurer.java:228) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer.init(OAuth2AuthorizationServerConfigurer.java:69) ~[spring-security-oauth2-authorization-server-0.3.1.jar:0.3.1]
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:338) ~[spring-security-config-5.7.3.jar:5.7.3]
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:300) ~[spring-security-config-5.7.3.jar:5.7.3]
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38) ~[spring-security-config-5.7.3.jar:5.7.3]
at org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration.authorizationServerSecurityFilterChain(OAuth2AuthorizationServerConfiguration.java:55) ~[spring-security-oauth2-authorization-server-0.3.1.jar:5.7.3]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.3.jar:2.7.3]
at in.thirumal.OauthAuthorizationServerApplication.main(OauthAuthorizationServerApplication.java:14) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.7.3.jar:2.7.3]
Khanh Nguyen
Have you checked this error “java.lang.ClassNotFoundException: org.springframework.security.cas.jackson2.CasJackson2Module”? I think you need to have the lib spring-security-cas in your Maven dependency.
Sanam Udash
I am using MySQL as the database my client is register in database but when i try to get the token i am getting response unauthorized:
phriend
I get the example from github of authoriztion server, then I change the database to mysql, and I got the same error
Khanh Nguyen
Which error do you guys mean? Can you please attach the error message?
Marcus Lombardi
Amazing article! Thanks! By the way, do you know how to pass the role parameter in the JWT to access to protect endpoints in Resource Server with those?
Mihajlo Stankov
Great article Khanh! Tnx!
Manikandan TK
Thanks nice article
I get too many redirection error when I started using JDBC, But when I use Inmemory database it is working fine
I do not know why its happening. Any Idea please. Thanks in advance
Ricardo
It happened to me also when mi registered client is like the Spring Authorization Server git project example (with the registered client for this example it works ok). It put TRACE log and compared with the log for InMemory and it has a Access denied example.
Any idea how to solve this issued is welcome
Khanh Nguyen
I can help but I need the error occurred. Please give me the code.
Raul
Hi, thanks for these articles, they are really helpful. It would be great if you could cover the dynamic client registration endpoint ( /connect/register ) and the userinfo ( /userinfo ), both available in version 0.2.1.
Caleb
Thank you for the article. It is very informative. Is there currently any way to configure the authorization server to store the generated authentication tokens in the database, so when the authorization server is restarted, the authentication tokens that haven’t expired yet are still recognized by the authorization server?
Caleb
I found tutorials https://huongdanjava.com/generate-keystore-with-pkcs12-format-using-keytool-of-java.html and https://huongdanjava.com/define-json-web-key-set-for-authorization-server-using-spring-authorization-server-and-pkcs12-key-store-file.html. I think they hold the key for which I’m looking.
Khanh Nguyen
Glad to hear that.
I will have a tutorial for storing access tokens.
abdou
A tutorial for storing access tokens is availble??.
sungpark Kim
thank you! great article!!