Showing posts with label jwt. Show all posts
Showing posts with label jwt. Show all posts

Wednesday, September 12, 2018

How to combine the windows authentication and JWT with .Net Core 2.1

Leave a Comment

I have tried to use the windows authentication and JWT together with .NET Core 2.1.

I have following startup settings of the authentication:

services.AddAuthentication(options =>                 {                     options.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme;                     options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;                 })                 .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>             {                 options.TokenValidationParameters = new TokenValidationParameters                 {                     ValidateIssuer = true,                     ValidateAudience = true,                     ValidateLifetime = true,                     ValidateIssuerSigningKey = true,                      ValidIssuer = "Test",                     ValidAudience = "Test",                     IssuerSigningKey = JwtSecurityKey.Create("677efa87-aa4d-42d6-adc8-9f866e5f75f7")                 };                  options.Events = new JwtBearerEvents()                 {                     OnAuthenticationFailed = OnAuthenticationFailed                 };             }); 

IIS settings:

"iisSettings": {     "windowsAuthentication": true,      "anonymousAuthentication": true,      ..   } 

I have tried following code snippet to create the JWT token with windows authentication:

[Route("api/[controller]")]     [ApiController]     [Authorize(AuthenticationSchemes = "Windows")]     public class AuthController : ControllerBase     {         [HttpPost("token")]         public IActionResult Token()         {             //Setup claims             var claims = new[]             {                 new Claim(ClaimTypes.Name, User.Identity.Name),                 //Add additional claims             };              //Read signing symmetric key             var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("677efa87-aa4d-42d6-adc8-9f866e5f75f7"));             var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);              //Create a token             var token = new JwtSecurityToken(                 issuer: "Test",                 audience: "Test",                 claims: claims,                 expires: DateTime.Now.AddMinutes(30),                 signingCredentials: creds);              //Return signed JWT token             return Ok(new             {                 token = new JwtSecurityTokenHandler().WriteToken(token)             });         }     } 

And in another controller I need use only JWT authentication:

[Route("api/[controller]")]     [ApiController]     [Authorize(AuthenticationSchemes = "Bearer")]     public class ProductController : ControllerBase     {         [HttpGet]         public IActionResult Get()         {             var userName = User.Identity.Name;              var claims = User.Claims.Select(x => new { x.Type, x.Value });              return Ok(new { userName, claims });         }     } 

If the JWT token is expired then I correctly received the response code 401 but I still get the dialog in the browser for putting the credentials.

How can I configure the windows authentication only for a part when I want to create the JWT token and disable response which is responsible for showing the browser dialog with credentials? How to correctly combine these things?

1 Answers

Answers 1

This answer might help: https://stackoverflow.com/a/51055082/1212994

You need to ensure, that you NOT setting Authorization: Bearer HTTP header when you trying to use Windows Auth. The key point here is how "Windows Auth" actually works. Let's look how it works with browser for example.

Read More

Wednesday, July 11, 2018

How to configure Resource Server in Spring Security for it to use additional information in JWT token

Leave a Comment

I have an oauth2 jwt token server configured to set additional info about the user authorities.

@Configuration @Component public class CustomTokenEnhancer extends JwtAccessTokenConverter {      CustomTokenEnhancer(){         super();     }      @Override     public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {         // TODO Auto-generated method stub         MyUserDetails user = (MyUserDetails) authentication.getPrincipal();         final Map<String, Object> additionalInfo = new HashMap<>();         @SuppressWarnings("unchecked")         List<GrantedAuthority> authorities= (List<GrantedAuthority>) user.getAuthorities();         additionalInfo.put("authorities", authorities);          ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);          return accessToken;     }  } 

I am not sure how to configure my resource server to extract the user authorities set by the oauth2 server and use that authority to be used for @Secured annotated controllers in Spring Security framework.

My Auth server configuration looks like this:

@Configuration @EnableAuthorizationServer public class OAuth2Config extends AuthorizationServerConfigurerAdapter {      @Value("${config.oauth2.privateKey}")     private String privateKey;      @Value("${config.oauth2.publicKey}")     private String publicKey;      @Value("{config.clienturl}")     private String clientUrl;      @Autowired     AuthenticationManager authenticationManager;      @Bean     public JwtAccessTokenConverter customTokenEnhancer(){          JwtAccessTokenConverter customTokenEnhancer = new CustomTokenEnhancer();         customTokenEnhancer.setSigningKey(privateKey);          return customTokenEnhancer;     }      @Bean     public JwtTokenStore tokenStore() {         return new JwtTokenStore(customTokenEnhancer());     }       @Override     public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {         oauthServer                 .tokenKeyAccess("isAnonymous() || hasRole('ROLE_TRUSTED_CLIENT')") // permitAll()                 .checkTokenAccess("hasRole('TRUSTED_CLIENT')"); // isAuthenticated()     }       @Override     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {         endpoints           .authenticationManager(authenticationManager)         .tokenStore(tokenStore())         .accessTokenConverter(customTokenEnhancer()) ;     }      @Override     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {          String url = clientUrl;          clients.inMemory()           .withClient("public")          .authorizedGrantTypes("client_credentials", "implicit")         .scopes("read")         .redirectUris(url)          .and()           .withClient("eagree_web").secret("eagree_web_dev")         //eagree_web should come from properties file?         .authorities("ROLE_TRUSTED_CLIENT")          .authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token")         .scopes("read", "write", "trust")          .redirectUris(url).resourceIds("dummy");     } } 

And my Resource Server configuration looks like this:

@Configuration @EnableResourceServer public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter {        @Value("{config.oauth2.publicKey}")     private String publicKey;      @Autowired     CustomTokenEnhancer tokenConverter;      @Autowired     JwtTokenStore jwtTokenStore;      @Bean     public JwtTokenStore jwtTokenStore() {         tokenConverter.setVerifierKey(publicKey);         jwtTokenStore.setTokenEnhancer(tokenConverter);         return jwtTokenStore;     }      @Bean     public ResourceServerTokenServices defaultTokenServices() {         final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();         defaultTokenServices.setTokenEnhancer(tokenConverter);         defaultTokenServices.setTokenStore(jwtTokenStore());         return defaultTokenServices;     }       @Override     public void configure(HttpSecurity http) throws Exception {         super.configure(http);         // @formatter:off         http                 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)                 .and()                 .requestMatchers()                 .antMatchers("/**")                 .and()                 .authorizeRequests()                 .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()                 .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')")                 .antMatchers(HttpMethod.PATCH, "/api/**").access("#oauth2.hasScope('write')")                 .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')")                 .antMatchers(HttpMethod.PUT, "/api/**").access("#oauth2.hasScope('write')")                 .antMatchers(HttpMethod.DELETE, "/api/**").access("#oauth2.hasScope('write')")                 .antMatchers("/admin/**").access("hasRole('ROLE_USER')");          // @formatter:on     }      @Override     public void configure(ResourceServerSecurityConfigurer resources) throws Exception {         System.out.println("Configuring ResourceServerSecurityConfigurer ");         resources.resourceId("dummy").tokenServices(defaultTokenServices());     }  } 

My test case is failing miserably saying:

{"error":"invalid_token","error_description":"Cannot convert access token to JSON"}

How do I get the Authentication object out of the JWT. How do I authenticate the client, with client credentials. How do I use @Secured annotation on my resource controllers.

What code is used on the resource server side to decode the token in order to extract client credentials and what code gets to user role verified?

Please help, as I already spent 2 days banging my head on this seemingly easy task.

Note: I receive the token from Auth server as: {access_token=b5d89a13-3c8b-4bda-b0f2-a6e9d7b7a285, token_type=bearer, refresh_token=43777224-b6f2-44d7-bf36-4e1934d32cbb, expires_in=43199, scope=read write trust, authorities=[{authority=ROLE_USER}, {authority=ROLE_ADMIN}]}

Please explain the concepts and point out if anything is missing from my configuration. I need to know the best practices in configuring my resource and auth server please.

1 Answers

Answers 1

In the following I'm referring to this Baeldung tutorial that I already implemented successfully: http://www.baeldung.com/spring-security-oauth-jwt

First at all: The CustomTokenEnhancer is used on the AuthorizationServer side to enhance a created token with additional custom information. You should use the so called DefaultAccessTokenConverter on the ResourceServer side to extract these extra claims.

You can @Autowire the CustomAccessTokenConverter into your ResourceServerConfiguration class and then set it to your JwtTokenStore() configuration.

ResourceServerConfiguration:

@Autowired private CustomAccessTokenConverter yourCustomAccessTokenConverter;  @Bean public TokenStore tokenStore() {     return new JwtTokenStore(accessTokenConverter()); }  @Bean public JwtAccessTokenConverter accessTokenConverter() {     JwtAccessTokenConverter converter = new JwtAccessTokenConverter();     converter.setAccessTokenConverter(yourCustomAccessTokenConverter);     converter.setSigningKey(yourSigningKey);     return converter; } 

The CustomAccessTokenConverter can be configured, so that the custom claims get extracted here.

CustomAccessTokenConverter:

@Component public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {      @Override     public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {         OAuth2Authentication authentication = super.extractAuthentication(claims);         authentication.setDetails(claims);         return authentication;     }  } 

(see: https://github.com/Baeldung/spring-security-oauth/blob/master/oauth-resource-server-1/src/main/java/org/baeldung/config/CustomAccessTokenConverter.java )

Read More

Monday, July 9, 2018

Return JWT token when user signs in rails

Leave a Comment

Having an issue with getting JWT token using devise gem and devise-jwt gem. This is how my confirmation looks like.

devise.rb

  Devise.setup do |config|      config.jwt do |jwt|       jwt.secret =  SECRETS.devise_jwt_secret_key       jwt.dispatch_requests = [ ['POST', %r{^/authentication_tokens/create$}] ]     end end  

user.rb

class User < ApplicationRecord      devise :database_authenticatable, :registerable,            :recoverable, :rememberable, :trackable, :validatable,            :jwt_authenticatable, jwt_revocation_strategy: Devise::JWT::RevocationStrategies::Null    end 

authentication_tokens_controller.rb

class Api::V1::AuthenticationTokensController < Devise::SessionsController   include Devise::Controllers::Helpers   skip_before_action :verify_authenticity_token     prepend_before_action :require_no_authentication, only: [:create]    before_action :rewrite_param_names, only: [:create]    def new     render json: { response: "Authentication required" }, status: 401   end    def create     self.resource = warden.authenticate!(auth_options)     sign_in(resource_name, resource)     yield resource if block_given?      render json: {success: true, jwt: current_token, response: "Authentication successful" }   end    private    def rewrite_param_names     request.params[:user] = {email: request.params[:email], password: request.params[:password]}   end    def current_token     request.env['warden-jwt_auth.token']   end  end 

routes.rb

   get 'home#secret'    devise_for :users    resources :tasks    #other routes for the website removed for brevity    namespace :api, defaults: { format: :json } do     namespace :v1 do       resources :users       devise_scope :user do         post '/authentication_tokens/create', to: "authentication_tokens#create"       end     end   end 

For some reason request.env['warden-jwt_auth.token'] returns null all the time, however, the user is authenticated. Is there anything that I need to add to get the JWT token when a user signs in?

Update - routes and namespacing

After days of debugging, I believe I have found the source of my problem. My app has a frontend which uses normal routes. The code above doesn't work however if I do something like the code below. All is good.

  scope :api, defaults: {format: :json} do     devise_for :users, controllers: {sessions: 'v1/authentication_tokens'}   end 

Is there a way of namespacing the devise_for for me API even though it has been used above for the website?

2 Answers

Answers 1

I've briefly looked on your issue and, it's probably wrong, but something for you to give a try:

looking on the following lines

def create   self.resource = warden.authenticate!(auth_options) end  def current_token   request.env['warden-jwt_auth.token'] end 

If you say that user is being authenticated even with nil returned from current_token method, so that means that jwt is passing correctly, but your way of fetching it is wrong.

Try to debug self.resource = warden.authenticate!(auth_options) line and see what contains inside auth_options, probably you can take JWT from there, or you just trying to get warden-jwt_auth.token in a wrong way. Try to debug this line as well and see if you should probably take "warden-jwt_auth.token" from request.headers["warden-jwt_auth.token"], or something like this. Just print out the whole response of your request and search by needed header.

I hope this helps!

Answers 2

You just need to make your route RESTful.

routes.rb

post '/authentication_tokens', to: "authentication_tokens#create" 

devise.rb

config.jwt do |jwt|   jwt.secret =  SECRETS.devise_jwt_secret_key   jwt.dispatch_requests = [ ['POST', %r{^/authentication_tokens$}] ] end 
Read More

Saturday, March 31, 2018

AngularJS token authentication with sliding expiration in state transitions with ui-router version 1.x

Leave a Comment

In our application we have a requirement that user should be logged in for a certain amount of time which is configurable by system admin, say 10 minutes. We have another requirement that the when user navigates to different parts of the app, this time should be refreshed and set back to that configured amount.

Our application is written in AngularJS and we use ui-router for routing, So when user navigates between different states, time to be logged out gets updated.

The back-end is written with .NET and we use jwt tokens for authentication, Token has a field named expiration. In the beginning of each request we check if the token is not expired.

I have a problem that I don't know how to tell the server that it should update the token expiration time, I am using ui-router version 1 and it has some hooks for doing server side things before state transitions, I ended up with something like this:

  $transitions.onBefore({       to: "*"   }, function(trans) {            // update the client ui, and also tell the server to update      // the timeout in the serverside and database       return authService.refreshToken();   }); 

But I am uncertain about this approach being correct, I couldn't find a good solutions for such problem in a REST architecture, I would be very grateful if you could tell me the pros and cons of this method or point me to the right implmentation

2 Answers

Answers 1

THEORY

As far as I can see, JWT standards doesn't really tell about refresh. (https://tools.ietf.org/rfc/rfc7519.txt)

If I well understand your problem, you want somebody's token to be renewed automatically after X minutes of inactivity. I guess this approach you want is a sliding sessions.

You can see a good article about it there: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/

The best practice in such case is not to extend the life of the token but to request a new one. You will find many articles and conventions talking about it. For security reasons, the shorter it is, the most secure it is.

Even if it is written for oauth, Here is a really good article listing different ways of token management : https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/


USE CASE

In your API, i would provide a refreshToken that permit to renew the token trough an HTTP request.

In you Front, I would make a service that store the last transition date, let say lastTransitionDate = new DateTime(). It will also store, the token, the refreshToken and the expiration date of the token.

Now When you have a transition,

  1. You check if the token is still valid,
  2. If the token is no more valid and if the lastTransitionDate is more than X minutes ago, you force the logout.
  3. If the token is no more valid but the lastTransitionDate is less than X minutes, then you ask for a new token thanks to your refreshToken.
  4. After all checks you reset lastTransitionDate.

The only things you need to be sure of is that, X is enough to make sure that a user won't be disconnected if he just passed some time reading some stuff on a page without triggering a transition.

Answers 2

Well, you cannot simply refresh the expiry of the token without changing it. This is because the expiry is coded in the token itself. So, when you want to change the expiry of the token, you need to change the token itself.

Being specific to your case, if you want to refresh user's timeout threshold, the server will have to create a new token for each request and send it back in response (using headers, maybe). The UI will have to store this token in the storage after the request completes.

This way, the UI will always have a latest JWT available with it. And, you don't have to make a call such as authService.refreshToken() as server automatically takes care of it, which is kind of an inefficient approach.

Also, if user is inactive for sometime (say 10 minutes), and then makes a request to the server, the JWT sent from the UI is already expired, and the server can signal the UI to expire the session.

Read More

Sunday, September 24, 2017

Socket.connect() is not consistent when using connectParams with JWT

Leave a Comment

I'm using https://github.com/auth0/socketio-jwt to connect the user to my node.js/socket.io server and I'm using one round trip

My problem right now is that whenever user logs in on the IOS part, the socket.connect() is not consistent, my theory is that the token is not yet ready even before the socket.connect() gets invoked.

I'm using Singleton design for my Socket.io class as many people pointed that out.

Here's the code on the SocketManager.swift part

import SocketIO  class SocketIOManager: NSObject {      static let sharedInstance = SocketIOManager()     var socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": getToken()])]) // getToken() I got it from other file which is Constant.Swift      func establishConnection() {         socket.connect()     }      func closeConnection() {         socket.disconnect()     }    } 

I'm using KeychainAccess to store the token and Constant.Swift file store all the global variables and functions so that I could call it on any Swift files.

Constant.Swift

import Foundation import KeychainAccess  let keychain = Keychain(server: "www.example.com", protocolType: .https)  func getToken() -> String {     if let token = keychain["token"] {         return token     }     return "" } 

LoginViewController.swift

 @IBAction func facebookButtonClicked(_ sender: UIButton) {        Alamofire.request("/login", method: .post, parameters: parameters, encoding: JSONEncoding.default)             .responseJSON { response in                 if let value = response.result.value {                     let json = JSON(value)                      self.keychain["token"] = String(describing: json["token"])                     SocketIOManager.sharedInstance.establishConnection()                      self.segueToAnotherVC() // Segue to another screen, to simplify things i put it in a function                 }         }   } 

So technically what is happening in this controller is, when the user logs in, I will store the token into KeychainAccess (it is equivalent to NSUserDefaults), then only I will make a socket connection because the socket connection needs a token beforehand.

What should I do to make the connection consistent all the time, whenever user logs in? Any methods that I could use?

0 Answers

Read More

Saturday, March 18, 2017

JWT authentication in SignalR (.NET Core) without passing token in Query String

Leave a Comment

I am using JWT authentication tokens in an ASP .NET Core Web API application. The tokens are generated by the API itself, not by a third party. I added SignalR sucessfully to the stack, but now I need to authenticate the users that are trying to execute server (Hub) methods. Someone suggested to pass the token in the "qs" property in JavaScript. This will not work for me as our tokens are really large (they contain lots of claims). I tried writing a custom middleware for reading the token from the payload and auto-authenticating the user. The problem is that, when using WebSockets, the middleware is not executed. Any ideas will help.

1 Answers

Answers 1

Have a look at article that suggests to use query string Authenticate against a ASP.NET Core 1.0 (vNext) SignalR application using JWT. I know that you token is too long, but author explains how to use middleware to authenticate the request.

Here is the summary from the article:

  • SignalR does not have any special authentication mechanism built in, it is using the standard ASP.NET authentication.
  • JWT is typically sent in the Authorization header of a request
  • The SignalR JavaScript client library does not include the means to send headers in the requests, it does however allow you to pass a query string
  • If we pass the token in the query string we can write a middleware that adds a authorization header with the token as its value. This must be done before the Jwt middleware in the pipeline
  • Be aware of the “Bearer ” format

I have highlighted the key point that your custom middleware should be registered before Jwt middleware.

Read More

Tuesday, February 28, 2017

Jwt tokens authorization is not working

Leave a Comment

I'm trying to create Jwt token authorization. For this purpose I have issuer part with the code like that:

public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) {     context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});     Users user;     using (var db = new UserStore())     {         user = Task.Run(()=> db.FindUser(context.UserName, context.Password, context.ClientId)).Result;     }     if (user == null)     {         context.SetError("invalid_grant", "The user name or password is incorrect");         return Task.FromResult<object>(null);     }     var identity = new ClaimsIdentity("JWT");     identity.AddClaim(new Claim(ClaimTypes.Name, user.Email));     identity.AddClaim(new Claim("sub", context.UserName));     identity.AddClaim(new Claim(ClaimTypes.Role, user.Roles.Name));      var props = new AuthenticationProperties(new Dictionary<string, string>     {         {             "audience", context.ClientId ?? string.Empty         }     });     var ticket = new AuthenticationTicket(identity, props);     context.Validated(ticket);     return Task.FromResult<object>(null); } 

And "resource" part that should accept bearer token:

public void ConfigureOAuth(IAppBuilder app) {     var issuer = SiteGlobal.Issuer;     var audience = SiteGlobal.Audience;     var secret = TextEncodings.Base64Url.Decode(SiteGlobal.Secret);     app.UseJwtBearerAuthentication(     new JwtBearerAuthenticationOptions     {         AuthenticationMode = AuthenticationMode.Active,         AllowedAudiences = new[] { audience },         IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]         {             new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)         }     }); } 

As far as I can see issued token are valid (I did validation on jwt.io), so the problem is somehwere else. When I'm sending token in Postman with the call to controller protected by [Authorize] attribute it always return 401 code. Could you please advise how to fix this?

P.S. This is how I implement custom Jwt fortmat:

public string Protect(AuthenticationTicket data) {     if (data == null)     {         throw new ArgumentNullException("data");     }     string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null;     if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");     Audience audience;     using (var store = new AudienceStore())     {         audience = Task.Run(()=> store.FindAudience(audienceId)).Result;     }     var symmetricKeyAsBase64 = audience.Base64Secret;     var signingKey = new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(symmetricKeyAsBase64));     var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);     var issued = data.Properties.IssuedUtc;     var expires = data.Properties.ExpiresUtc;     var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingCredentials);     var handler = new JwtSecurityTokenHandler();     var jwt = handler.WriteToken(token);     return jwt; } 

P.S. Guys, I'm so sorry, but I forgot to explain that "issuer" part of code that's standalone application, meanwhile "audience" is protected web api. That's two different appliactions running independently.

2 Answers

Answers 1

In Postman ensure you are sending the authorization header using the following format:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 

Postman Authorization Header

Ensure that you leave the Authorization tab set to Type: No Auth.

If you continue to have issues, set a breakpoint in your GrantResourceOwnerCredentials and see if it gets to that point. Also consider overriding the ValidateClientAuthentication method of OAuthAuthorizationServerProvider which should get called prior to GrantResourceOwnerCredentials if you want to debug earlier in the chain of events.

Answers 2

I have just tried to run demo project mentioned in SON Web Token in ASP.NET Web API 2 using Owin and all worked as expected.

I noticed that your implementation of Protect method differs quite a bit. I would suggest you to compare your implementation to an example given in the article. Try make that work first.

Also please make sure that issuer, audience and secret are same on both servers.

If you provide complete source code I can try to investigate more.

Read More

Laravel 5.3 - Social login doubts

Leave a Comment

I am developing a mobile app and currently depending on JWT to maintain the statelessness of the API. The API is consumed by mobile and web devices. The users will use their email and password to register.

I am assigned to implement social login option in this API. I would like to clear my following doubts.

1) When Social Login is used, how can I generate a token [like JWT] which will be stored at the client's end? This token is supposed to send with all subsequent requests after login.

2) In case social platforms are not providing/sharing email address [which is one of our primary keys], what all information shall I store?

2 Answers

Answers 1

Once you "social login" a user, you get a list of data from the social network itself. User can disallow the retrieve of the email address (ex. from Facebook): in this case, you have to create a new user in you database, connect this user with the ID received and ask him to enter his email address. After the social login, if it is the first time, I suggest you to ask the user to confirm their email address or even change it: in this way, you have just one flow.

Pay attention that a user could register himself using email/password and then try to login using Facebook or Twitter: in this case you should try and check if you already have a user with that email address and just link this user with the new token. Otherwise, create a new user.

The token is created as you actually do, after a successful login.

Answers 2

Some social networks allow to delegate user authentication instead or requiring credentials in your own system. When user logs in, the external platform will provide you an access token that can be used to get some information of the user,

Use this data to register user into your own system. Attach the access token. Depending on the permissions you have requested, you can use the token to perform additional operation in the social platform.

Then issue a JWT to be used as authentication token in the web/mobile app where user log on. This JWT must be independent of the access token sent by authentication provider. For example

 {"sub": "userid",    "name": "User name"    "iss": "issuer",    "exp": 1300819380,    "login":"facebook"   } 

If you plan to use several authentication systems like Google or Facebook, do not use the email as unique identifier because it could different for the same user. You will need an additional register process to link the accounts that the user has in different networks. For example, letting user set the identifier that is using in other system or just launch the log in process in twitter when user is logged by Facebook

Read More

Sunday, January 29, 2017

Route avaliable with or without token JWT+PASSPORT

Leave a Comment

I want that I can acess a router with or without a token. If user has a token, than give me req.user

Like this:

router.get('/profile', function(req, res) { if(req.user) { // or if (req.isAuthenticated())  res.send('logged') } else {  res.send('not loggedIn') } }); 

My app:

var JwtStrategy = require('passport-jwt').Strategy, ExtractJwt = require('passport-jwt').ExtractJwt; var opts = {} opts.jwtFromRequest = ExtractJwt.fromAuthHeader(); opts.secretOrKey = 'sh'; passport.use(new JwtStrategy(opts, function(jwt_payload, done) { User.findOne({id: jwt_payload.sub}, function(err, user) {     if (err) {         return done(err, false);     }     if (user) {         done(null, user);     } else {         done(null, false);         // or you could create a new account     } }); })); 

If I try to access /profile without a token, works fine. But, when a try to access /profile with a token in header give me not loggedIn

I want to access it even without a token and, if I provided a toke, give me the user.

ps: Already tested using passport.authenticate('jwt') in route and works. If I give token let me access, if not give me unauthorized.

2 Answers

Answers 1

Change you router as follows

router.get('/profile', authenticateUser(), profile());  function authenticateUser(req, res, next) {   // your strategy here...   if (authenticated) {      req.user = user;     next();   } else {     return res.status(401).send("Not authenticated");   } }  function profile(req, res, next) {   var userId = req.user.id;   User.findById(userId, function(err, user) {     if (err) { return res.status(500).json(err); }     return res.json(user);   }) } 

Answers 2

you should be using one of the below to access request data

if (req.params.user) {do something...} 

or

if (req.body.user) {do something...} 

the request object has no user attribute.

Read More

Sunday, July 31, 2016

How to secure REST API for SPA and Mobile App using Cordova

Leave a Comment

I've done a lot of research on "best practices" surrounding this and have read blog post after blog post, SO question after SO question, and OWASP article after OWASP article. I've arrived at a few clear answers but some unknowns.

First, the "Do's":

  1. Use JWT for authorizing users on my REST API [1] [2]
  2. Store the JWT in a HTTPOnly/Secure cookie and build in CSRF protection. Do NOT store in HTML5 local storage [3] [4] [5] (Actually, this point is debatable, is it easier to protect against XSS or CSRF? [6])
  3. Verify the signing method of the JWT [7]

Now I started with the assumption that having a SPA (built with Angular) and using HTML5 sessionStorage would be secure enough for short-lived tokens, but there is a point to be made that XSS attacks can happen from a "bad actor" originating in the one of many libraries loaded in from a CDN.

For my specific use case, I do not plan on having long-lived tokens - expiration after 10 minutes of non-use but I'm still figuring out if I want to track expiration by session or use refresh tokens - StormPath recommends the former (no longer stateless?) but I believe big players using JWTs use refresh tokens (Google uses them but states you need to store them in secure, long-term storage which means HTML5 localStorage is again, out of the question).

I would like to make it so my users don't have to log back in if they refresh the page (hence the need to store the token on the client side). I would also like to use my SPA as a "mobile app" with the help of Cordova. The obvious pitfall here is that if I use cookies, there is no baked-in cookie support/storage with Cordova and I'm urged to switch to HTML5 local storage instead. Since on mobile I don't really need to worry about refreshing pages, I can just let my token live in memory and expire with the strategy I settle on.

If I take this approach, cookie-based JWT on Desktop, "Bearer" headers on mobile, I now need an authentication end-point that will give tokens two different ways, and when I authorize on the REST API side, I need to support both cookie-based JWTs (with CSRF) and header based JWT verification. This complication has me worried as I don't know if I can accurately foresee security implications here.

To summarize the barrage of thoughts above:

  • Create an authentication handler that would hand out tokens via HttpOnly/Secure cookies to desktop, and by payload for mobile.
  • On my REST API, support both methods of verification - header based and cookie-based - including CSRF protection for the cookie-based approach.

Is there any reason why I wouldn't want to take this approach? I assume if I take XSS on my SPA as a serious risk, then I need a classic login-page for authentication to set the proper cookies because if I do authentication via the SPA, then any XSS attack could potentially intercept that as well (both on mobile and Desktop)! However, on mobile, I'd need to inject the JWT into SPA, maybe through some custom DOM element (meta tag?), but at that point I can just let the SPA perform the login and not consider XSS a threat on mobile devices. Cordova packages all assets into the install package so that's somewhat better but then why not take the same approach on the Desktop version?

My application takes very little user input, it is primarily a dashboard/reporting tool. There will be a "message center" but it's content should always be user-created (by only that user) and sanitized. In my use-case then, would it be ok to deviate from "best practices" and rely on localStorage not counting XSS as a serious risk for my SPA? This would simplify this entire thing (use HTML5 sessionStorage as originally planned) and reduce complexity, which would reduce attack surface for potential security blunders. I just want to make sure I understand the risks before moving forward.

Is there no secure way to make this secure other than by building a native app for mobile and not using Cordova to convert my SPA to a mobile app? I'd hate for this to be the case, but it might very well be.

I'd appreciate all thoughts on the matter!

0 Answers

Read More

Thursday, March 31, 2016

PHP Azure OAuth JWT App Roles

Leave a Comment

I've created an application in an Azure AD from a manifest with several appRoles inside of it, and I can assign users to these roles. After a user completes the single sign on, returns to my application and I then request a JSON Web Token from their login. The problem is, there are no assigned roles listed in the token I get back from Azure, as it would suggest there's supposed to be here.

Is there a configuration option I'm missing or is there an alternate way to find out their assigned role through the Azure Graph API?


Update:

After specifying the resource as the App ID URI when requesting the authorisation URL I've managed to get a little further.

I'm now getting back the following error (in the return URL):

"The signed in user '<user email>' is not assigned to a role for the application '<app client id>'." 

The user has definitely been assigned a role in the Azure AD control panel for the app, and the app client id in the error message matches the app's client id exactly.


Application config:

Azure AD Application config screen

User assigned a role:

Azure AD Application user role assignments

Error message after logging in and returning to app:

Azure AD Authentication error message

1 Answers

Answers 1

@Phlip,Could you please try to set your application permission using PowerShell?

#1.down load Azure AD powershell and login in using your user in AD $msolcred=get-credential connect-msolservice -credential $msolcred  #2. get principal Id  $ClientIdWebApp = '5b597c35-**-**-ad05-***' $webApp = Get-MsolServicePrincipal –AppPrincipalId $ClientIdWebApp  # 3. use Add-MsolRoleMember to add it to “Company Administrator” role). Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId $webApp.ObjectId 

For more information, please refer to this page: https://msdn.microsoft.com/en-us/library/azure/dn919663.aspx and Use this methods to add member into role:

Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberEmailAddress "user@contoso.com" 

Any updates or results, please let me know.

Read More