I am trying to integrate spring oauth2 (java based config not boot) with angular 6,
my WebSecurityConfigurerAdapter.java file is :
package com.novowash.authentication;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
NovoAuthenticationProvider novoAuthenticationProvider;
@Autowired
UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private PasswordEncoder userPasswordEncoder;
@Autowired
@Qualifier("dataSource")
DataSource dataSource;
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
/*auth.inMemoryAuthentication()
.withUser("bill").password("abc123").roles("ADMIN").and()
.withUser("bob").password("abc123").roles("USER");*/
auth.authenticationProvider(novoAuthenticationProvider);
// auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(userPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/oauth/token").permitAll()
.antMatchers("/signup").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
my Authentication provider is :
package com.novowash.authentication;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import com.novowash.Enums.CommonEnums;
import com.novowash.model.User;
import com.novowash.service.UserService;
/**
* @author manish
*
* This Class is responsible for authentication and
* access control of users to cube root Admin module over http in extension of AuthenticationProvider interface of Spring web framework .
*
*/
@Component("novoAuthenticationProvider")
public class NovoAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = Logger.getLogger(NovoAuthenticationProvider.class);
@Autowired UserService userService;
/* (non-Javadoc)
* @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication)
*/
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
logger.debug( "ImageVideoAuthenticationProvider.authenticate() authentication.getPrincipal(): " + authentication.getPrincipal());
logger.debug( "ImageVideoAuthenticationProvider.authenticate() authentication.getCredentials(): " + authentication.getCredentials());
String userName = authentication.getPrincipal().toString();
String password = authentication.getCredentials().toString();
User user = userService.findUserByMobile(userName);
if (user == null) {
throw new UsernameNotFoundException(String.format(URLEncoder.encode("Invalid Email OR password", "UTF-8"), authentication.getPrincipal()));
}
if (CommonEnums.STATUS.INACTIVE.ID == user.getStatus()) {
throw new UsernameNotFoundException(String.format(URLEncoder.encode("You are not active", "UTF-8"), authentication.getPrincipal()));
}
if (CommonEnums.STATUS.BLOCK.ID == user.getStatus()) {
throw new UsernameNotFoundException(String.format(URLEncoder.encode("You are blocked. Please contact admin", "UTF-8"), authentication.getPrincipal()));
}
List<String> roles=null;
if(user != null){
roles= userService.getUserRoles(user.getId());
}
List<GrantedAuthority> grantList= new ArrayList<GrantedAuthority>();
if(roles!= null) {
for(String role: roles) {
// ROLE_USER, ROLE_ADMIN,..
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + role);
grantList.add(authority);
}
}
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, password, grantList);
return token;
} catch (Exception e) {
logger.error( "Error in ImageVideoAuthenticationProvider.authenticate()", e);
throw new AuthenticationServiceException(e.getMessage());
}
}
/* (non-Javadoc)
* @see org.springframework.security.authentication.AuthenticationProvider#supports(java.lang.Class)
*/
public boolean supports(Class<?> clazz) {
return clazz.equals(UsernamePasswordAuthenticationToken.class);
}
}
I have already add the CORSFilter.java .
Angular 6 service:
import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
import { Inject, Injectable } from "@angular/core";
import { OAuthService } from "angular-oauth2-oidc";
import { environment } from "../../environments/environment";
import { Observable } from "rxjs/Observable";
import { map, combineLatest } from 'rxjs/operators';
@Injectable()
export class ROPCService {
private _user: any;
constructor(private httpClient: HttpClient, private oauthService: OAuthService) {}
public async login(username: string, password: string) {
debugger;
const body = new HttpParams()
.set('username', username)
.set('password', password)
.set('grant_type', environment.auth.grantType);
const headers = new HttpHeaders()
.set("Content-type", "application/x-www-form-urlencoded; charset=utf-8")
.set("Authorization", "Basic d2ViOnNlY3JldA==");
this.httpClient
.post(this.oauthService.tokenEndpoint, body.toString(), {headers:headers})
.pipe(map((res: any) => {
debugger;
})).subscribe(
data => {
debugger;
},
err => {
debugger;
}
)
}
public logOut() {
if (this.oauthService.getRefreshToken() === null) {
return;
}
const refreshToken = this.oauthService.getRefreshToken();
const accessToken = this.oauthService.getAccessToken();
this.oauthService.logOut(true);
const body = new HttpParams().set("client_id", this.oauthService.clientId).set("refresh_token", refreshToken);
return this.httpClient.post(this.oauthService.logoutUrl, body.toString(), {
headers: new HttpHeaders().set("Content-Type", "application/x-www-form-urlencoded"),
});
}
public get user() {
return this._user;
}
public set user(user) {
this._user = user;
}
}
when i call /oauth/token URL i got 401 error my request is:
I have got the error in backend :
2018-08-02 11:52:09 DEBUG DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'delegatingApplicationListener' 2018-08-02 11:52:09 DEBUG ExceptionTranslationFilter:174 - Access is denied (user is anonymous); redirecting to authentication entry point org.springframework.security.access.AccessDeniedException: Access is denied at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) 2018-08-02 11:52:09 DEBUG AndRequestMatcher:66 - Trying to match using Ant [pattern='/', GET] 2018-08-02 11:52:09 DEBUG AntPathRequestMatcher:137 - Request 'OPTIONS /oauth/token' doesn't match 'GET / 2018-08-02 11:52:09 DEBUG AndRequestMatcher:69 - Did not match 2018-08-02 11:52:09 DEBUG HttpSessionRequestCache:62 - Request not saved as configured RequestMatcher did not match 2018-08-02 11:52:09 DEBUG ExceptionTranslationFilter:203 - Calling Authentication entry point. 2018-08-02 11:52:09 DEBUG DelegatingAuthenticationEntryPoint:78 - Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@781f892e, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[/]] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:185 - httpRequestMediaTypes=[] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:213 - Did not match any media types 2018-08-02 11:52:09 DEBUG DelegatingAuthenticationEntryPoint:78 - Trying to match using AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@781f892e, matchingMediaTypes=[text/html], useEquals=false, ignoredMediaTypes=[]]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@781f892e, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[/]]]] 2018-08-02 11:52:09 DEBUG AndRequestMatcher:66 - Trying to match using NegatedRequestMatcher [requestMatcher=MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@781f892e, matchingMediaTypes=[text/html], useEquals=false, ignoredMediaTypes=[]]] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:185 - httpRequestMediaTypes=[] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:213 - Did not match any media types 2018-08-02 11:52:09 DEBUG NegatedRequestMatcher:51 - matches = true 2018-08-02 11:52:09 DEBUG AndRequestMatcher:66 - Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@781f892e, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[/]] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:185 - httpRequestMediaTypes=[] 2018-08-02 11:52:09 DEBUG MediaTypeRequestMatcher:213 - Did not match any media types 2018-08-02 11:52:09 DEBUG AndRequestMatcher:69 - Did not match 2018-08-02 11:52:09 DEBUG DelegatingAuthenticationEntryPoint:91 - No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@5a1a107f 2018-08-02 11:52:09 DEBUG HstsHeaderWriter:130 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@5b4e497d 2018-08-02 11:52:09 DEBUG SecurityContextPersistenceFilter:119 - SecurityContextHolder now cleared, as request processing completed
It is exactly as the error you highlighted says. The request method you send was GET but it expects a OPTIONS method.
It is configured in the OAuth2SecurityConfig
:
.antMatchers(HttpMethod.OPTIONS,"/oauth/token").permitAll()
Change it to GET and it should work.
.antMatchers(HttpMethod.GET,"/oauth/token").permitAll()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With