I've implemented a custom PersistedGrantStore storing my refresh tokens in a xml file, however I now have problems refreshing my tokens.
When I remove following lines, the refresh works
services.AddTransient<IPersistedGrantService, PersistedGrantService>();
services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
When I put those lines back, I get the following in the logs :
2018-04-24 14:14:51.094 +02:00 [DBG] [IdentityServer4.Hosting.EndpointRouter] Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
2018-04-24 14:14:51.095 +02:00 [INF] [IdentityServer4.Hosting.IdentityServerMiddleware] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
2018-04-24 14:14:51.098 +02:00 [VRB] [IdentityServer4.Endpoints.TokenEndpoint] Processing token request.
2018-04-24 14:14:51.108 +02:00 [DBG] [IdentityServer4.Endpoints.TokenEndpoint] Start token request.
2018-04-24 14:14:51.115 +02:00 [DBG] [IdentityServer4.Validation.ClientSecretValidator] Start client validation
2018-04-24 14:14:51.120 +02:00 [DBG] [IdentityServer4.Validation.BasicAuthenticationSecretParser] Start parsing Basic Authentication secret
2018-04-24 14:14:51.123 +02:00 [DBG] [IdentityServer4.Validation.PostBodySecretParser] Start parsing for secret in post body
2018-04-24 14:14:51.145 +02:00 [DBG] [IdentityServer4.Validation.SecretParser] Parser found secret: PostBodySecretParser
2018-04-24 14:14:51.145 +02:00 [DBG] [IdentityServer4.Validation.SecretParser] Secret id found: UserPortal
2018-04-24 14:14:51.161 +02:00 [DBG] [IdentityServer4.Validation.SecretValidator] Secret validator success: HashedSharedSecretValidator
2018-04-24 14:14:51.161 +02:00 [DBG] [IdentityServer4.Validation.ClientSecretValidator] Client validation success
2018-04-24 14:14:51.167 +02:00 [VRB] [IdentityServer4.Endpoints.TokenEndpoint] Calling into token request validator: IdentityServer4.Validation.TokenRequestValidator
2018-04-24 14:14:51.173 +02:00 [DBG] [IdentityServer4.Validation.TokenRequestValidator] Start token request validation
2018-04-24 14:14:51.181 +02:00 [DBG] [IdentityServer4.Validation.TokenRequestValidator] Start validation of refresh token request
2018-04-24 14:14:51.186 +02:00 [VRB] [IdentityServer4.Validation.TokenValidator] Start refresh token validation
2018-04-24 14:14:51.228 +02:00 [DBG] [Nextel.VisitorManager.IdentityServer.Extensions.PersistedGrantStore] r9bsqJEQddM1Hhp6PzZwk/Zr3Yyb72PntfPZup+ik5Y= found in database: True
2018-04-24 14:14:51.992 +02:00 [ERR] [IdentityServer4.Validation.TokenValidator] Refresh token has expired. Removing from store.
2018-04-24 14:14:51.996 +02:00 [DBG] [Nextel.VisitorManager.IdentityServer.Extensions.PersistedGrantStore] removing r9bsqJEQddM1Hhp6PzZwk/Zr3Yyb72PntfPZup+ik5Y= persisted grant from database
2018-04-24 14:14:52.002 +02:00 [ERR] [IdentityServer4.Validation.TokenRequestValidator] Refresh token validation failed. aborting.
2018-04-24 14:14:52.095 +02:00 [ERR] [IdentityServer4.Validation.TokenRequestValidator] {
"ClientId": "UserPortal",
"ClientName": "User Portal Client",
"GrantType": "refresh_token",
"Raw": {
"client_id": "UserPortal",
"client_secret": "***REDACTED***",
"grant_type": "refresh_token",
"refresh_token": "3314d145ec7dec80b8137b288c99a66b22798451dd77a8878466139da29a3c13",
"scope": "offline_access"
}
}
2018-04-24 14:14:52.098 +02:00 [VRB] [IdentityServer4.Hosting.IdentityServerMiddleware] Invoking result: IdentityServer4.Endpoints.Results.TokenErrorResult
Which seems to show it does find the refresh token in the store, but then deletes it and returns an invalid_grant
This is my PersistedGrantStore:
public class PersistedGrantStore : IPersistedGrantStore
{
#region Declarations
private readonly ILogger logger;
private readonly IPersistedGrantService persistedGrantService;
#endregion
#region Constructor
public PersistedGrantStore(IPersistedGrantService persistedGrantService, ILogger<PersistedGrantStore> logger)
{
this.persistedGrantService = persistedGrantService;
this.logger = logger;
}
#endregion
#region Methods
public Task StoreAsync(PersistedGrant token)
{
var existing = persistedGrantService.GetByKey(token.Key);
if (existing == null)
{
logger.LogDebug($"{token.Key} not found in database");
persistedGrantService.Add(token);
}
else
{
logger.LogDebug($"{token.Key} found in database");
persistedGrantService.Update(token);
}
return Task.FromResult(0);
}
public Task<PersistedGrant> GetAsync(string key)
{
var persistedGrant = persistedGrantService.GetByKey(key);
logger.LogDebug($"{key} found in database: {persistedGrant != null}");
return Task.FromResult(persistedGrant);
}
public Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
{
var persistedGrants = persistedGrantService.GetBySubject(subjectId);
logger.LogDebug($"{persistedGrants.Count} persisted grants found for {subjectId}");
return Task.FromResult(persistedGrants.AsEnumerable());
}
public Task RemoveAsync(string key)
{
var persistedGrant = persistedGrantService.GetByKey(key);
if (persistedGrant != null)
{
logger.LogDebug($"removing {key} persisted grant from database");
persistedGrantService.Remove(persistedGrant);
}
else
logger.LogDebug($"no {key} persisted grant found in database");
return Task.FromResult(0);
}
public Task RemoveAllAsync(string subjectId, string clientId)
{
var persistedGrants = persistedGrantService.GetBySubjectClient(subjectId, clientId);
logger.LogDebug($"removing {persistedGrants.Count} persisted grants from database for subject {subjectId}, clientId {clientId}");
persistedGrantService.Remove(persistedGrants);
return Task.FromResult(0);
}
public Task RemoveAllAsync(string subjectId, string clientId, string type)
{
var persistedGrants = persistedGrantService.GetBySubjectClientType(subjectId, clientId, type);
logger.LogDebug($"removing {persistedGrants.Count} persisted grants from database for subject {subjectId}, clientId {clientId}, grantType {type}");
persistedGrantService.Remove(persistedGrants);
return Task.FromResult(0);
}
#endregion
}
And this is my PersistedGrantService:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
namespace Nextel.VisitorManager.IdentityServer.Extensions
{
public class PersistedGrantService : IPersistedGrantService
{
#region Declarations
private readonly ILogger logger;
private List<PersistedGrant> persistedGrants;
private readonly string xmlFile;
#endregion
#region Constructor
public PersistedGrantService(IHostingEnvironment env, ILogger<PersistedGrantStore> logger)
{
this.logger = logger;
xmlFile = env.ContentRootPath + #"\PersistedGrants.xml";
}
#endregion
#region Methods
public PersistedGrant GetByKey(string key)
{
if (persistedGrants != null || ReadXml())
return persistedGrants.FirstOrDefault(x => x.Key == key);
return null;
}
public List<PersistedGrant> GetBySubject(string subjectId)
{
if (persistedGrants != null || ReadXml())
return persistedGrants.Where(x => x.SubjectId == subjectId).ToList();
return null;
}
public List<PersistedGrant> GetBySubjectClient(string subjectId, string clientId)
{
if (persistedGrants != null || ReadXml())
return persistedGrants.Where(x => x.SubjectId == subjectId && x.ClientId == clientId).ToList();
return null;
}
public List<PersistedGrant> GetBySubjectClientType(string subjectId, string clientId, string type)
{
if (persistedGrants != null || ReadXml())
return persistedGrants.Where(x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type).ToList();
return null;
}
public void Add(PersistedGrant item)
{
if (persistedGrants != null || ReadXml())
{
persistedGrants.Add(item);
SaveXml();
}
}
public void Update(PersistedGrant item)
{
if (persistedGrants != null || ReadXml())
{
var index = persistedGrants.FindIndex(x => x.Key == item.Key);
persistedGrants[index] = item;
SaveXml();
}
}
public void Remove(PersistedGrant item)
{
if (persistedGrants != null || ReadXml())
{
persistedGrants.Remove(item);
SaveXml();
}
}
public void Remove(List<PersistedGrant> items)
{
if (persistedGrants != null || ReadXml())
{
foreach (var item in items)
{
persistedGrants.Remove(item);
}
SaveXml();
}
}
#region Privates
private bool ReadXml()
{
try
{
if (File.Exists(xmlFile))
{
var deserializer = new XmlSerializer(typeof(List<PersistedGrant>));
using (TextReader reader = new StreamReader(xmlFile))
{
persistedGrants = (List<PersistedGrant>)deserializer.Deserialize(reader);
}
}
else
persistedGrants = new List<PersistedGrant>();
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "Error in reading XML");
return false;
}
}
private bool SaveXml()
{
try
{
if (persistedGrants != null)
{
var serializer = new XmlSerializer(typeof(List<PersistedGrant>));
using (TextWriter writer = new StreamWriter(xmlFile))
{
serializer.Serialize(writer, persistedGrants);
}
}
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "Error in saving XML");
return false;
}
}
#endregion
#endregion
}
}
With this interface:
public interface IPersistedGrantService
{
PersistedGrant GetByKey(string key);
List<PersistedGrant> GetBySubject(string subjectId);
List<PersistedGrant> GetBySubjectClient(string subjectId, string clientId);
List<PersistedGrant> GetBySubjectClientType(string subjectId, string clientId, string type);
void Add(PersistedGrant item);
void Update(PersistedGrant item);
void Remove(PersistedGrant item);
void Remove(List<PersistedGrant> items);
}
I had almost similar code for refreshing the token and was spending hours together to resolve the same issue.
Found out that the Client configuration should have "RefreshTokenExpiration" attribute set as TokenExpiration.Absolute and "RefreshTokenUsage" attribute is set to "OneTimeOnly". This should make it work !
Related
I am trying to authenticate a request from using spring security, I have followed few blogs and videos but i am not able to fix the issues.
Security configuration is loaded but my requests are not getting authenticated. I get 403 error
Bean class in WebSecurityConfigureAdapter
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
System.out.println(userDetailsService());
return authProvider;
}
over riding configure method
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/products","/orders").hasAnyRole("admin");//.authenticated();
}
user details services overridding loadUserByUsername
#Override
public UserDetails loadUserByUsername(String loginName) {
String authenticated = "false";
UserDetails userDetails = null;
List<Users> usersList = usersRepository.findByLoginName(loginName);
if(usersList.size()==0) {
return null;
}else {
for (Users users : usersList) {
List<Roles> rolesList = users.getRoles();
for (Roles roles : rolesList) {
if(roles.getUserRole().equalsIgnoreCase("admin")) {
authenticated = "admin";
GrantedAuthority authority = new SimpleGrantedAuthority(authenticated);
User user = new User(users.getLoginName(),users.getPassword(),Arrays.asList(authority));
userDetails = (UserDetails)user;
}
}
}
return userDetails;
}
using postman setting up the credentials as basicAuth, its throwing 403 error
the issue was...
we need to either set the value for different getters in userdetails class or explicitly set to true
i have below getters explicitly set it to true, it worked for me
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#SpringBootApplication
public class SpringDataSolarApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataSolarApplication.class, args);
}
#Bean
SolrTemplate solrTemplate() {
return new SolrTemplate(solrClientFactory());
}
#Bean
SolrClientFactory solrClientFactory() {
Credentials credentials = new UsernamePasswordCredentials("solr", "SolrRocks");
return new HttpSolrClientFactory(solrClient(), credentials , "BASIC");
}
#Bean
SolrClient solrClient() {
return new HttpSolrClient.Builder("http://localhost:8983/solr").build();
}
}
public interface EmployeeRepository extends SolrCrudRepository{
Employee findByName(String name);
}
#RestController
public class EmployeeController {
#Autowired
private EmployeeRepository repository;
#PostConstruct
public void addEmployees() {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("373", "Basant", new String[] { "Bangalore", "BTM" }));
employees.add(new Employee("908", "Santosh", new String[] { "Hyderbad", "XYZ" }));
employees.add(new Employee("321", "Sagar", new String[] { "Pune", "PQR" }));
repository.saveAll(employees);
}
#GetMapping("/getALL")
public Iterable<Employee> getEmployees() {
return repository.findAll();
}
#GetMapping("/getEmployee/{name}")
public Employee getEmployeeByName(#PathVariable String name) {
return repository.findByName(name);
}
}
the getALL operation is working fine but the save operation failed with this error. Please help
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.7.jar:4.5.7]
... 63 common frames omitted
Came across same issue and solved with extending HttpSolrClient and applying same backend approach with recommended way mentioned on Solr docs but getting credentials from constructor not setting on each request.
class CustomSolrClient extends HttpSolrClient {
#Nullable
private final String username;
#Nullable
private final String password;
CustomSolrClient(Builder builder, String username, String password) {
super(builder);
this.username = username;
this.password = password;
}
#Override
public NamedList<Object> request(SolrRequest request, ResponseParser processor, String collection) throws SolrServerException, IOException {
HttpRequestBase method = createMethod(request, collection);
if (username != null && password != null) {
String userPass = username + ":" + password;
String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
}
return executeMethod(method, processor, request instanceof V2Request || request.getPath().contains("/____v2"));
}
}
And create bean using that:
#Bean
public SolrClient solrClient() {
return new CustomSolrClient(new HttpSolrClient.Builder(properties.getHost()), properties.getUsername(), properties.getPassword());
}
This may seem as an ugly approach but if you check HttpSolrClientFactory sources it's even more uglier which actually accesses private field of HttpClient belongs to Solr client.
I have a multitenant app secure with an IdentityServer4 implementation. I recently updated it to the latest ID4 and the behavior seems to have changed. Previously, I could make a request with the TokenClient inside of the IdentityModel package:
var parameters = new Dictionary<string, string>();
parameters.Add("username", loginModel.UserName);
parameters.Add("password", loginModel.Password);
var tokenClient = new TokenClient(new Uri(new Uri(accountsConfig.EndpointUrl), "/connect/token").ToString(), accountsConfig.ClientId, accountsConfig.Secret, null, AuthenticationStyle.PostValues);
var tokenResponse = await tokenClient.RequestCustomGrantAsync("AgentLogin", extra: parameters);
It would return all of the scopes defined for the client in the token. That is no longer the case. How do I configure ID4 to do that without explicitly requesting them inside of the TokenClient?
public class AgentLoginCustomGrantValidator : IExtensionGrantValidator
{
private readonly ILogger<AgentLoginCustomGrantValidator> _logger;
private readonly IAdminUserService _adminUserService;
public AgentLoginCustomGrantValidator(ILogger<AgentLoginCustomGrantValidator> logger, IAdminUserService adminUserService)
{
_logger = logger;
_adminUserService = adminUserService;
}
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
try
{
var username = context.Request.Raw.Get("username");
var password = context.Request.Raw.Get("password");
var userId = _adminUserService.AuthenticateUser(username, password);
if (userId != null)
{
var agencyUser = _adminUserService.GetUser(userId.Value);
context.Result = new GrantValidationResult($"{userId}", GrantType, agencyUser.Roles.Select(x => new Claim(JwtClaimTypes.Role, x.Name)).Concat(new List<Claim>() { new Claim(JwtClaimTypes.Name, agencyUser.UserName) { } }));
}
else
{
_logger.LogWarning($"Bum creds: {username} ");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, "Invalid credentials");
}
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, ex.Message);
}
}
public string GrantType => "AgentLogin";
}
Looks like Identity Server 4 by default only returns the requested identity or api resources for each client. However, this behaviour can be easily overridden to return all the scopes regardless whether they were requested in the token request or not. You can create a CustomClaimsService which inherits from the DefaultClaimsService.
public class CustomClaimsService : DefaultClaimsService
{
public CustomClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger) : base(profile, logger)
{
}
public override async Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject,
Resources resources, ValidatedRequest request)
{
var baseResult = await base.GetAccessTokenClaimsAsync(subject, resources, request);
var outputClaims = baseResult.ToList();
//If there are any allowed scope claims that are not yet in the output claims - add them
foreach (var allowedClientScope in request.Client.AllowedScopes)
{
if (!outputClaims.Any(x => x.Type == JwtClaimTypes.Scope && x.Value == allowedClientScope))
{
outputClaims.Add(new Claim(JwtClaimTypes.Scope, allowedClientScope));
}
}
return outputClaims;
}
}
Then just register it with the IdentityServerBuilder service container.
var builder = services.AddIdentityServer(options =>
{
//Your identity server options
});
//Register the custom claims service with the service container
builder.Services.AddTransient<IClaimsService, CustomClaimsService>();
Each access token will now contain all the scopes that the given client is allowed.
I'm building a desktop APP using windows forms that needs to be authenticated via a WebAPI using Token authentication.
The API is proved that work because a mobile APP is using it and also I can get results using POSTMAN
The problem is when I'm calling the Authentication method from the desktop App.
When I do the request, the API recieves it and it only goes until ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context), not reaching GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) in the Auth process.
Here is my CustomAuthProvider
public class CustomOAuthProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var allowedOrigin = "*";
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "El nombre de usuario o contraseƱa son incorrectos");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
var ticket = new AuthenticationTicket(oAuthIdentity, null);
context.Validated(ticket);
}
}
Here is my Startup class
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
HttpConfiguration httpConfig = new HttpConfiguration();
ConfigureOAuthTokenGeneration(app);
ConfigureOAuthTokenConsumption(app);
ConfigureWebApi(httpConfig);
}
}
At the moment I'm trying two different ways to authenticate the APP.
First One:
public LoginResponseModel Authenticate(LoginRequestModel applicationUser)
{
using (var client = new WebClient())
{
try
{
client.Headers["Content-Type"] = "application/json";
var data = applicationUser.Serialize();
var response = client.UploadString(Context.ApiUrl + "Authenticate","POST", JsonConvert.SerializeObject(applicationUser));
var resultJson = JsonConvert.DeserializeObject<LoginResponseModel>(response);
return resultJson;
}
catch (Exception exception)
{
}
}
return null;
}
And second one:
public async Task<ApplicationUser> Authenticate(LoginRequestModel applicationUser)
{
var client = new HttpClient();
try
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var data = applicationUser.Serialize();
var response = await client.PostAsJsonAsync(Context.ApiUrl + "Authenticate",data );
// return null by default (test)
return null;
}
catch (Exception exception)
{
}
return null;
}
And this is the model I'm using for the request
public class LoginRequestModel
{
public string Grant_type { get; set; } = "Password";
public string UserName { get; set; }
public string Password { get; set; }
}
And this should be the response:
public class LoginResponseModel
{
public string Access_token { get; set; }
public string Token_type { get; set; }
public string Expires_in { get; set; }
}
Ah the moment both ways of calling the API only reach the initial verification of the owin process (ValidateClientAuthentication). What can be happening? How I can fix this? What I need to do to make the process go to GrantResourceOwnerCredentials?
thanks for the help
I solved my problem. The problem was that the form wasn't being filled and sent correctly.
private AuthToken GetAuthToken(LoginRequestModel applicationUser)
{
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", applicationUser.UserName},
{"password", applicationUser.Password},
};
try
{
var tokenResponse = client.PostAsync(Context.ApiUrl + "Authenticate", new FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<AuthToken>(new[] { new JsonMediaTypeFormatter() }).Result;
return token;
}
catch (Exception e)
{
Log4Net.log.Error("Error Getting Auth token", e);
return null;
}
}
}
Have a problem with CORS filter, i think.
Because when i send request with Authorization header by Intellij Idea REST Tools, my filter catch a Authorization header.
But when i try to send request from client side from another server, filter does not see my header(return null).
I`m using spring boot, angularjs, salelizer and JWT for build token.
Params for building token on server side.
private static final JWSHeader JWT_HEADER = new JWSHeader(JWSAlgorithm.HS256);
private static final String TOKEN_SECRET = "Bearer";
public static final String AUTH_HEADER_KEY = "Authorization";
My Auth filter
public class AuthFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader(AuthUtils.AUTH_HEADER_KEY);
if (StringUtils.isBlank(authHeader) || authHeader.split(" ").length != 2) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, AUTH_ERROR_MSG);
} else {
JWTClaimsSet claimSet = null;
try {
claimSet = (JWTClaimsSet) AuthUtils.decodeToken(authHeader);
} catch (ParseException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_ERROR_MSG);
return;
} catch (JOSEException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_INVALID_MSG);
return;
}
// ensure that the token is not expired
if (new DateTime(claimSet.getExpirationTime()).isBefore(DateTime.now())) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, EXPIRE_ERROR_MSG);
} else {
chain.doFilter(request, response);
}
}
}
#Override
public void destroy() { /* unused */ }
#Override
public void init(FilterConfig filterConfig) throws ServletException { /* unused */ }
}
My CORS filter in Web Mvc config file
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
config.addExposedHeader("Content-Type");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
My security configure
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"**").permitAll().and().authorizeRequests()
.antMatchers( "/index","/api/**", "/auth/**", "/js/**", "/css/**", "/html/**")
.permitAll().anyRequest().authenticated();
My cliend side configs
function configHttp($httpProvider, $authProvider){
console.log("sdfd");
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
var token = sessionStorage.getItem("satellizer_token");
if (token && $authProvider.httpInterceptor) {
token = $authProvider.authHeader === 'Authorization' ? 'Bearer ' + token : token;
$httpProvider.defaults.headers.common[$authProvider.authHeader] = token;
}
}
function configAuth($authProvider) {
$authProvider.httpInterceptor = function() { return true; };
$authProvider.baseUrl = 'http://localhost:8080';
$authProvider.loginUrl = '/auth/login';
$authProvider.signupUrl = '/auth/registration';
$authProvider.tokenName = 'token';
$authProvider.storageType = 'sessionStorage';
$authProvider.authToken = 'Bearer';
$authProvider.authHeader = 'Authorization';
}
There are a few options described here.
One option would be to annotate your controller method or class with #CrossOrigin.
If you want global config, you could add a new bean. I took this from the Spring doc listed above and modified it so that the mapping is /*. You can modify that path to be suitable for your application. According to the javadoc all origins will be allowed by default.
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*");
}
};
}