Spring security: get password in UserDetailsServiceMethod
In order to get my account I have a external spring application that I need to login at. Why I need it is not important but in order to do a /login call on the API I need to get the password in the UserDetailsServiceMethod. Here is my security setup:
//https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
//Constructor gets authLogic for external authentication
@Autowired
public WebSecurity(@Qualifier("authLogic") UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(BANK_API, INVENTORY_API, MARKET_API)); //TODO: is dit correct??
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
My UserDetailsServiceMethod implementation:
@Service
public class AuthLogic implements UserDetailsService {
private HttpServletRequest request;
private IAccountRepository accountRepository;
private RestCallLogic restCall;
@Autowired
public AuthLogic(HttpServletRequest request, IAccountRepository accountRepository, RestCallLogic restCall){
this.request = request;
this.accountRepository = accountRepository;
this.restCall = restCall;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//get password
//make restcall to external login
}
}
Is there a way I can get the password while using the spring security implementation. Because I could easily make my own class and do the login from there but it would be nice to use Spring security for it. Also the login returns a token that I can reform to a User. Maybe i'm just overthinking...
In order to make a API call i needed to write a custom AuthenticationProvider:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails principal = new User(username, password, new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
java spring spring-security
add a comment |
In order to get my account I have a external spring application that I need to login at. Why I need it is not important but in order to do a /login call on the API I need to get the password in the UserDetailsServiceMethod. Here is my security setup:
//https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
//Constructor gets authLogic for external authentication
@Autowired
public WebSecurity(@Qualifier("authLogic") UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(BANK_API, INVENTORY_API, MARKET_API)); //TODO: is dit correct??
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
My UserDetailsServiceMethod implementation:
@Service
public class AuthLogic implements UserDetailsService {
private HttpServletRequest request;
private IAccountRepository accountRepository;
private RestCallLogic restCall;
@Autowired
public AuthLogic(HttpServletRequest request, IAccountRepository accountRepository, RestCallLogic restCall){
this.request = request;
this.accountRepository = accountRepository;
this.restCall = restCall;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//get password
//make restcall to external login
}
}
Is there a way I can get the password while using the spring security implementation. Because I could easily make my own class and do the login from there but it would be nice to use Spring security for it. Also the login returns a token that I can reform to a User. Maybe i'm just overthinking...
In order to make a API call i needed to write a custom AuthenticationProvider:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails principal = new User(username, password, new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
java spring spring-security
2
No you don't... You need a customAuthenticationProvider
not a customUserDetailsService
. You are trying to solve it in the wrong place.
– M. Deinum
Nov 23 '18 at 12:14
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
But yourAuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that yourJwtAuthenticationFilter
is actually producing aUsernamePasswordAuthentication
.
– M. Deinum
Nov 24 '18 at 18:01
add a comment |
In order to get my account I have a external spring application that I need to login at. Why I need it is not important but in order to do a /login call on the API I need to get the password in the UserDetailsServiceMethod. Here is my security setup:
//https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
//Constructor gets authLogic for external authentication
@Autowired
public WebSecurity(@Qualifier("authLogic") UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(BANK_API, INVENTORY_API, MARKET_API)); //TODO: is dit correct??
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
My UserDetailsServiceMethod implementation:
@Service
public class AuthLogic implements UserDetailsService {
private HttpServletRequest request;
private IAccountRepository accountRepository;
private RestCallLogic restCall;
@Autowired
public AuthLogic(HttpServletRequest request, IAccountRepository accountRepository, RestCallLogic restCall){
this.request = request;
this.accountRepository = accountRepository;
this.restCall = restCall;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//get password
//make restcall to external login
}
}
Is there a way I can get the password while using the spring security implementation. Because I could easily make my own class and do the login from there but it would be nice to use Spring security for it. Also the login returns a token that I can reform to a User. Maybe i'm just overthinking...
In order to make a API call i needed to write a custom AuthenticationProvider:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails principal = new User(username, password, new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
java spring spring-security
In order to get my account I have a external spring application that I need to login at. Why I need it is not important but in order to do a /login call on the API I need to get the password in the UserDetailsServiceMethod. Here is my security setup:
//https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
//Constructor gets authLogic for external authentication
@Autowired
public WebSecurity(@Qualifier("authLogic") UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(BANK_API, INVENTORY_API, MARKET_API)); //TODO: is dit correct??
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
My UserDetailsServiceMethod implementation:
@Service
public class AuthLogic implements UserDetailsService {
private HttpServletRequest request;
private IAccountRepository accountRepository;
private RestCallLogic restCall;
@Autowired
public AuthLogic(HttpServletRequest request, IAccountRepository accountRepository, RestCallLogic restCall){
this.request = request;
this.accountRepository = accountRepository;
this.restCall = restCall;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//get password
//make restcall to external login
}
}
Is there a way I can get the password while using the spring security implementation. Because I could easily make my own class and do the login from there but it would be nice to use Spring security for it. Also the login returns a token that I can reform to a User. Maybe i'm just overthinking...
In order to make a API call i needed to write a custom AuthenticationProvider:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails principal = new User(username, password, new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
java spring spring-security
java spring spring-security
edited Nov 23 '18 at 13:54
spoilerd do
asked Nov 23 '18 at 11:24
spoilerd dospoilerd do
205
205
2
No you don't... You need a customAuthenticationProvider
not a customUserDetailsService
. You are trying to solve it in the wrong place.
– M. Deinum
Nov 23 '18 at 12:14
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
But yourAuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that yourJwtAuthenticationFilter
is actually producing aUsernamePasswordAuthentication
.
– M. Deinum
Nov 24 '18 at 18:01
add a comment |
2
No you don't... You need a customAuthenticationProvider
not a customUserDetailsService
. You are trying to solve it in the wrong place.
– M. Deinum
Nov 23 '18 at 12:14
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
But yourAuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that yourJwtAuthenticationFilter
is actually producing aUsernamePasswordAuthentication
.
– M. Deinum
Nov 24 '18 at 18:01
2
2
No you don't... You need a custom
AuthenticationProvider
not a custom UserDetailsService
. You are trying to solve it in the wrong place.– M. Deinum
Nov 23 '18 at 12:14
No you don't... You need a custom
AuthenticationProvider
not a custom UserDetailsService
. You are trying to solve it in the wrong place.– M. Deinum
Nov 23 '18 at 12:14
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
But your
AuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that your JwtAuthenticationFilter
is actually producing a UsernamePasswordAuthentication
.– M. Deinum
Nov 24 '18 at 18:01
But your
AuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that your JwtAuthenticationFilter
is actually producing a UsernamePasswordAuthentication
.– M. Deinum
Nov 24 '18 at 18:01
add a comment |
2 Answers
2
active
oldest
votes
Behind the scene, Spring Security parses user's credentials in filter (ex. BasicAuthenticationFilter
, UsernamePasswordAuthenticationFilter
etc. - the filters retrieves user credentials), if such filter successfully retrieved user's credentials it passes such credentials to AuthenticationProvider
to verify credentials and create user's details (read more about AuthenticationProvider). The AuthenticationProvider
can verify credentials on various way.
One of the implementation of AuthenticationProvider
is DaoAuthenticationProvider
which tries to find user by username in UserDetailsService
and if it found it gets UserDetails
for the user from UserDetailsService
and then checks if password provided by the user is satisfing the password in UserDetails
.
In your case you need to make such request not in UserDetailsService
, but in AuthenticationProvider
because it's responsible for such case.
My suggestion is to extend AbstractUserDetailsAuthenticationProvider
class from spring security and implement your functionality in abstract method protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
.
For example:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
The better example: look how DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider
in spring security.
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
add a comment |
After a week I finally got what I wanted. So i made a custom authentication provider that will make a REST call to my authentication API. If the username and password I gave are correct I'll get a JWT-token back that contains a username, roles and a ID. after that I just call a custom Authentication service that checks if the user id already exists in its database. If that isn't the case than I'll create a new user with the given id from the JWT-token.
Here is my custom authentication provider:
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//custom authentication service
private AuthLogic userDetailsImpl;
public JwtAuthenticationProvider(AuthLogic userDetailsImpl) {
this.userDetailsImpl = userDetailsImpl;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//JWTUser is a custom class that extends the UserDetails class from spring
JwtUser user = (JwtUser) userDetails;
//call the custom auth service to check if the user exists in the database
userDetailsImpl.loadUserByUsername(user.getUserID(), user.getUsername());
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//get the token from a external authentication API
String token = retrieveAccountData(new LoginWrapper(username, authentication.getCredentials().toString()));
Claims claims = Jwts.parser()
.setSigningKey(JWTKEY)
.parseClaimsJws(token)
.getBody();
List<String> scopes = (List<String>) claims.get("scopes");
int UserId = (int) claims.get("userID");
List<GrantedAuthority> authorities = scopes.stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
//return the User
return new JwtUser(UserId, username, authentication.getCredentials().toString(), authorities);
}
private String retrieveAccountData(LoginWrapper loginWrapper){
URI uri = UriComponentsBuilder.fromUriString(BANK_LOGIN).build().toUri();
Gson gson = new GsonBuilder().create();
RequestEntity<String> request = RequestEntity
.post(uri)
.accept(MediaType.APPLICATION_JSON)
.body(gson.toJson(loginWrapper));
//post call
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
//check if status code is correct
if(response.getStatusCode() != HttpStatus.OK) {
throw new UsernameNotFoundException(loginWrapper.getUsername());
}
//convert to LoginWrapper
return gson.fromJson(response.getBody(), TokenWrapper.class).getToken();
}
}
And here is my custom authentication service:
@Service
public class AuthLogic {
private IAccountRepository accountRepository;
@Autowired
public AuthLogic(IAccountRepository context) {
this.accountRepository = context;
}
trough with the jwt token)
public UserDetails loadUserByUsername(int userId, String username) throws UsernameNotFoundException {
Optional<Account> foundAccount = accountRepository.findById(userId);
Account account;
//check if user has logged in to our inventory API before, if not create new account
if (!foundAccount.isPresent()) {
account = accountRepository.save(new Account(userId, username));
} else {
account = foundAccount.get();
}
return new JwtUserPrincipal(account);
}
}
In order to call the service from the provider you need to configure your WebSecurityConfigurerAdapter properly:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private JwtAuthenticationProvider authenticationProvider;
@Autowired
public WebSecurity(@Qualifier("authLogic") AuthLogic userDetailsImpl) {
this.authenticationProvider = new JwtAuthenticationProvider(userDetailsImpl);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
I hope this answer helps.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445809%2fspring-security-get-password-in-userdetailsservicemethod%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Behind the scene, Spring Security parses user's credentials in filter (ex. BasicAuthenticationFilter
, UsernamePasswordAuthenticationFilter
etc. - the filters retrieves user credentials), if such filter successfully retrieved user's credentials it passes such credentials to AuthenticationProvider
to verify credentials and create user's details (read more about AuthenticationProvider). The AuthenticationProvider
can verify credentials on various way.
One of the implementation of AuthenticationProvider
is DaoAuthenticationProvider
which tries to find user by username in UserDetailsService
and if it found it gets UserDetails
for the user from UserDetailsService
and then checks if password provided by the user is satisfing the password in UserDetails
.
In your case you need to make such request not in UserDetailsService
, but in AuthenticationProvider
because it's responsible for such case.
My suggestion is to extend AbstractUserDetailsAuthenticationProvider
class from spring security and implement your functionality in abstract method protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
.
For example:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
The better example: look how DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider
in spring security.
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
add a comment |
Behind the scene, Spring Security parses user's credentials in filter (ex. BasicAuthenticationFilter
, UsernamePasswordAuthenticationFilter
etc. - the filters retrieves user credentials), if such filter successfully retrieved user's credentials it passes such credentials to AuthenticationProvider
to verify credentials and create user's details (read more about AuthenticationProvider). The AuthenticationProvider
can verify credentials on various way.
One of the implementation of AuthenticationProvider
is DaoAuthenticationProvider
which tries to find user by username in UserDetailsService
and if it found it gets UserDetails
for the user from UserDetailsService
and then checks if password provided by the user is satisfing the password in UserDetails
.
In your case you need to make such request not in UserDetailsService
, but in AuthenticationProvider
because it's responsible for such case.
My suggestion is to extend AbstractUserDetailsAuthenticationProvider
class from spring security and implement your functionality in abstract method protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
.
For example:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
The better example: look how DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider
in spring security.
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
add a comment |
Behind the scene, Spring Security parses user's credentials in filter (ex. BasicAuthenticationFilter
, UsernamePasswordAuthenticationFilter
etc. - the filters retrieves user credentials), if such filter successfully retrieved user's credentials it passes such credentials to AuthenticationProvider
to verify credentials and create user's details (read more about AuthenticationProvider). The AuthenticationProvider
can verify credentials on various way.
One of the implementation of AuthenticationProvider
is DaoAuthenticationProvider
which tries to find user by username in UserDetailsService
and if it found it gets UserDetails
for the user from UserDetailsService
and then checks if password provided by the user is satisfing the password in UserDetails
.
In your case you need to make such request not in UserDetailsService
, but in AuthenticationProvider
because it's responsible for such case.
My suggestion is to extend AbstractUserDetailsAuthenticationProvider
class from spring security and implement your functionality in abstract method protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
.
For example:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
The better example: look how DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider
in spring security.
Behind the scene, Spring Security parses user's credentials in filter (ex. BasicAuthenticationFilter
, UsernamePasswordAuthenticationFilter
etc. - the filters retrieves user credentials), if such filter successfully retrieved user's credentials it passes such credentials to AuthenticationProvider
to verify credentials and create user's details (read more about AuthenticationProvider). The AuthenticationProvider
can verify credentials on various way.
One of the implementation of AuthenticationProvider
is DaoAuthenticationProvider
which tries to find user by username in UserDetailsService
and if it found it gets UserDetails
for the user from UserDetailsService
and then checks if password provided by the user is satisfing the password in UserDetails
.
In your case you need to make such request not in UserDetailsService
, but in AuthenticationProvider
because it's responsible for such case.
My suggestion is to extend AbstractUserDetailsAuthenticationProvider
class from spring security and implement your functionality in abstract method protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
.
For example:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
The better example: look how DaoAuthenticationProvider
extends AbstractUserDetailsAuthenticationProvider
in spring security.
edited Nov 23 '18 at 13:51
answered Nov 23 '18 at 13:37
Andrew SashaAndrew Sasha
434212
434212
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
add a comment |
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
Do i have to do any other configurations in the WebSecurityConfigureAdapter. Cause I started making a custom AuthenticationProvider class and it doesn't get triggered when I do /login it just says Acces Denied.
– spoilerd do
Nov 23 '18 at 14:00
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
One more question: where do i put my call to the database to check if the account exists in my local database?
– spoilerd do
Nov 28 '18 at 10:23
add a comment |
After a week I finally got what I wanted. So i made a custom authentication provider that will make a REST call to my authentication API. If the username and password I gave are correct I'll get a JWT-token back that contains a username, roles and a ID. after that I just call a custom Authentication service that checks if the user id already exists in its database. If that isn't the case than I'll create a new user with the given id from the JWT-token.
Here is my custom authentication provider:
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//custom authentication service
private AuthLogic userDetailsImpl;
public JwtAuthenticationProvider(AuthLogic userDetailsImpl) {
this.userDetailsImpl = userDetailsImpl;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//JWTUser is a custom class that extends the UserDetails class from spring
JwtUser user = (JwtUser) userDetails;
//call the custom auth service to check if the user exists in the database
userDetailsImpl.loadUserByUsername(user.getUserID(), user.getUsername());
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//get the token from a external authentication API
String token = retrieveAccountData(new LoginWrapper(username, authentication.getCredentials().toString()));
Claims claims = Jwts.parser()
.setSigningKey(JWTKEY)
.parseClaimsJws(token)
.getBody();
List<String> scopes = (List<String>) claims.get("scopes");
int UserId = (int) claims.get("userID");
List<GrantedAuthority> authorities = scopes.stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
//return the User
return new JwtUser(UserId, username, authentication.getCredentials().toString(), authorities);
}
private String retrieveAccountData(LoginWrapper loginWrapper){
URI uri = UriComponentsBuilder.fromUriString(BANK_LOGIN).build().toUri();
Gson gson = new GsonBuilder().create();
RequestEntity<String> request = RequestEntity
.post(uri)
.accept(MediaType.APPLICATION_JSON)
.body(gson.toJson(loginWrapper));
//post call
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
//check if status code is correct
if(response.getStatusCode() != HttpStatus.OK) {
throw new UsernameNotFoundException(loginWrapper.getUsername());
}
//convert to LoginWrapper
return gson.fromJson(response.getBody(), TokenWrapper.class).getToken();
}
}
And here is my custom authentication service:
@Service
public class AuthLogic {
private IAccountRepository accountRepository;
@Autowired
public AuthLogic(IAccountRepository context) {
this.accountRepository = context;
}
trough with the jwt token)
public UserDetails loadUserByUsername(int userId, String username) throws UsernameNotFoundException {
Optional<Account> foundAccount = accountRepository.findById(userId);
Account account;
//check if user has logged in to our inventory API before, if not create new account
if (!foundAccount.isPresent()) {
account = accountRepository.save(new Account(userId, username));
} else {
account = foundAccount.get();
}
return new JwtUserPrincipal(account);
}
}
In order to call the service from the provider you need to configure your WebSecurityConfigurerAdapter properly:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private JwtAuthenticationProvider authenticationProvider;
@Autowired
public WebSecurity(@Qualifier("authLogic") AuthLogic userDetailsImpl) {
this.authenticationProvider = new JwtAuthenticationProvider(userDetailsImpl);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
I hope this answer helps.
add a comment |
After a week I finally got what I wanted. So i made a custom authentication provider that will make a REST call to my authentication API. If the username and password I gave are correct I'll get a JWT-token back that contains a username, roles and a ID. after that I just call a custom Authentication service that checks if the user id already exists in its database. If that isn't the case than I'll create a new user with the given id from the JWT-token.
Here is my custom authentication provider:
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//custom authentication service
private AuthLogic userDetailsImpl;
public JwtAuthenticationProvider(AuthLogic userDetailsImpl) {
this.userDetailsImpl = userDetailsImpl;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//JWTUser is a custom class that extends the UserDetails class from spring
JwtUser user = (JwtUser) userDetails;
//call the custom auth service to check if the user exists in the database
userDetailsImpl.loadUserByUsername(user.getUserID(), user.getUsername());
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//get the token from a external authentication API
String token = retrieveAccountData(new LoginWrapper(username, authentication.getCredentials().toString()));
Claims claims = Jwts.parser()
.setSigningKey(JWTKEY)
.parseClaimsJws(token)
.getBody();
List<String> scopes = (List<String>) claims.get("scopes");
int UserId = (int) claims.get("userID");
List<GrantedAuthority> authorities = scopes.stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
//return the User
return new JwtUser(UserId, username, authentication.getCredentials().toString(), authorities);
}
private String retrieveAccountData(LoginWrapper loginWrapper){
URI uri = UriComponentsBuilder.fromUriString(BANK_LOGIN).build().toUri();
Gson gson = new GsonBuilder().create();
RequestEntity<String> request = RequestEntity
.post(uri)
.accept(MediaType.APPLICATION_JSON)
.body(gson.toJson(loginWrapper));
//post call
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
//check if status code is correct
if(response.getStatusCode() != HttpStatus.OK) {
throw new UsernameNotFoundException(loginWrapper.getUsername());
}
//convert to LoginWrapper
return gson.fromJson(response.getBody(), TokenWrapper.class).getToken();
}
}
And here is my custom authentication service:
@Service
public class AuthLogic {
private IAccountRepository accountRepository;
@Autowired
public AuthLogic(IAccountRepository context) {
this.accountRepository = context;
}
trough with the jwt token)
public UserDetails loadUserByUsername(int userId, String username) throws UsernameNotFoundException {
Optional<Account> foundAccount = accountRepository.findById(userId);
Account account;
//check if user has logged in to our inventory API before, if not create new account
if (!foundAccount.isPresent()) {
account = accountRepository.save(new Account(userId, username));
} else {
account = foundAccount.get();
}
return new JwtUserPrincipal(account);
}
}
In order to call the service from the provider you need to configure your WebSecurityConfigurerAdapter properly:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private JwtAuthenticationProvider authenticationProvider;
@Autowired
public WebSecurity(@Qualifier("authLogic") AuthLogic userDetailsImpl) {
this.authenticationProvider = new JwtAuthenticationProvider(userDetailsImpl);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
I hope this answer helps.
add a comment |
After a week I finally got what I wanted. So i made a custom authentication provider that will make a REST call to my authentication API. If the username and password I gave are correct I'll get a JWT-token back that contains a username, roles and a ID. after that I just call a custom Authentication service that checks if the user id already exists in its database. If that isn't the case than I'll create a new user with the given id from the JWT-token.
Here is my custom authentication provider:
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//custom authentication service
private AuthLogic userDetailsImpl;
public JwtAuthenticationProvider(AuthLogic userDetailsImpl) {
this.userDetailsImpl = userDetailsImpl;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//JWTUser is a custom class that extends the UserDetails class from spring
JwtUser user = (JwtUser) userDetails;
//call the custom auth service to check if the user exists in the database
userDetailsImpl.loadUserByUsername(user.getUserID(), user.getUsername());
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//get the token from a external authentication API
String token = retrieveAccountData(new LoginWrapper(username, authentication.getCredentials().toString()));
Claims claims = Jwts.parser()
.setSigningKey(JWTKEY)
.parseClaimsJws(token)
.getBody();
List<String> scopes = (List<String>) claims.get("scopes");
int UserId = (int) claims.get("userID");
List<GrantedAuthority> authorities = scopes.stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
//return the User
return new JwtUser(UserId, username, authentication.getCredentials().toString(), authorities);
}
private String retrieveAccountData(LoginWrapper loginWrapper){
URI uri = UriComponentsBuilder.fromUriString(BANK_LOGIN).build().toUri();
Gson gson = new GsonBuilder().create();
RequestEntity<String> request = RequestEntity
.post(uri)
.accept(MediaType.APPLICATION_JSON)
.body(gson.toJson(loginWrapper));
//post call
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
//check if status code is correct
if(response.getStatusCode() != HttpStatus.OK) {
throw new UsernameNotFoundException(loginWrapper.getUsername());
}
//convert to LoginWrapper
return gson.fromJson(response.getBody(), TokenWrapper.class).getToken();
}
}
And here is my custom authentication service:
@Service
public class AuthLogic {
private IAccountRepository accountRepository;
@Autowired
public AuthLogic(IAccountRepository context) {
this.accountRepository = context;
}
trough with the jwt token)
public UserDetails loadUserByUsername(int userId, String username) throws UsernameNotFoundException {
Optional<Account> foundAccount = accountRepository.findById(userId);
Account account;
//check if user has logged in to our inventory API before, if not create new account
if (!foundAccount.isPresent()) {
account = accountRepository.save(new Account(userId, username));
} else {
account = foundAccount.get();
}
return new JwtUserPrincipal(account);
}
}
In order to call the service from the provider you need to configure your WebSecurityConfigurerAdapter properly:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private JwtAuthenticationProvider authenticationProvider;
@Autowired
public WebSecurity(@Qualifier("authLogic") AuthLogic userDetailsImpl) {
this.authenticationProvider = new JwtAuthenticationProvider(userDetailsImpl);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
I hope this answer helps.
After a week I finally got what I wanted. So i made a custom authentication provider that will make a REST call to my authentication API. If the username and password I gave are correct I'll get a JWT-token back that contains a username, roles and a ID. after that I just call a custom Authentication service that checks if the user id already exists in its database. If that isn't the case than I'll create a new user with the given id from the JWT-token.
Here is my custom authentication provider:
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//custom authentication service
private AuthLogic userDetailsImpl;
public JwtAuthenticationProvider(AuthLogic userDetailsImpl) {
this.userDetailsImpl = userDetailsImpl;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//JWTUser is a custom class that extends the UserDetails class from spring
JwtUser user = (JwtUser) userDetails;
//call the custom auth service to check if the user exists in the database
userDetailsImpl.loadUserByUsername(user.getUserID(), user.getUsername());
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//get the token from a external authentication API
String token = retrieveAccountData(new LoginWrapper(username, authentication.getCredentials().toString()));
Claims claims = Jwts.parser()
.setSigningKey(JWTKEY)
.parseClaimsJws(token)
.getBody();
List<String> scopes = (List<String>) claims.get("scopes");
int UserId = (int) claims.get("userID");
List<GrantedAuthority> authorities = scopes.stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
//return the User
return new JwtUser(UserId, username, authentication.getCredentials().toString(), authorities);
}
private String retrieveAccountData(LoginWrapper loginWrapper){
URI uri = UriComponentsBuilder.fromUriString(BANK_LOGIN).build().toUri();
Gson gson = new GsonBuilder().create();
RequestEntity<String> request = RequestEntity
.post(uri)
.accept(MediaType.APPLICATION_JSON)
.body(gson.toJson(loginWrapper));
//post call
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
//check if status code is correct
if(response.getStatusCode() != HttpStatus.OK) {
throw new UsernameNotFoundException(loginWrapper.getUsername());
}
//convert to LoginWrapper
return gson.fromJson(response.getBody(), TokenWrapper.class).getToken();
}
}
And here is my custom authentication service:
@Service
public class AuthLogic {
private IAccountRepository accountRepository;
@Autowired
public AuthLogic(IAccountRepository context) {
this.accountRepository = context;
}
trough with the jwt token)
public UserDetails loadUserByUsername(int userId, String username) throws UsernameNotFoundException {
Optional<Account> foundAccount = accountRepository.findById(userId);
Account account;
//check if user has logged in to our inventory API before, if not create new account
if (!foundAccount.isPresent()) {
account = accountRepository.save(new Account(userId, username));
} else {
account = foundAccount.get();
}
return new JwtUserPrincipal(account);
}
}
In order to call the service from the provider you need to configure your WebSecurityConfigurerAdapter properly:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private JwtAuthenticationProvider authenticationProvider;
@Autowired
public WebSecurity(@Qualifier("authLogic") AuthLogic userDetailsImpl) {
this.authenticationProvider = new JwtAuthenticationProvider(userDetailsImpl);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
I hope this answer helps.
answered Dec 4 '18 at 16:47
spoilerd dospoilerd do
205
205
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445809%2fspring-security-get-password-in-userdetailsservicemethod%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
No you don't... You need a custom
AuthenticationProvider
not a customUserDetailsService
. You are trying to solve it in the wrong place.– M. Deinum
Nov 23 '18 at 12:14
Thanks for the useful information!!! The only problem I have know is that my custom AuthenticationProvider doesn't trigger when i do /login
– spoilerd do
Nov 23 '18 at 13:53
But your
AuthenticatioNprovider
isn't calling anything? It only returns a user it doesn't do a call to an external system at all. Also I doubt that yourJwtAuthenticationFilter
is actually producing aUsernamePasswordAuthentication
.– M. Deinum
Nov 24 '18 at 18:01