• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Bear Bibeault
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh

What is the flow of authenticating requests in Spring security?

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm trying to understand the difference between the flow of
1) a login request
2) subsequent request using tokens

I think the first one goes from auth (UsernamePasswordAuthenticationFilter) filter (to get token holder object from request parameters [attemptAuthentication]) -> authManagerProvider (to confirm user exists) -> back to auth filter (for actions we wanna take on [successfulAuthentication] i.e. where the login response payload is built)

The second scenario skips the filter and goes to some underlying filter that grabs the incoming JWT, hydrates a user out of it and passes it to the UserDetail bean

My original aim is one endpoint for both login and registration. In my controller, I can easily check for user existence and sign in; otherwise, user is created on the fly and signed in. However, I have no way of obtaining the token except if JWT generation is abstracted away to a bean and autowired into my authentication/registration controller. Is this good practice? Or, should process be broken down into multiple steps i.e. API consumer makes extra request to registration endpoint if he user is not currently in existence. Then after registration completes, make another request with those credentials to login
 
Saloon Keeper
Posts: 13014
281
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, you really should not be doing anything security-related in your controllers. That's what the security filters are for.

How are the JWTs generated? Are you using one of the standard security filters, or did you insert a third-party filter into the filter chain?

If the filter that generates the JWT generates a token based on the SecurityContext provided by filters further down the chain, then you can solve this problem pretty easily: Just add a custom security filter at the end of the filter chain that does the following:

If the SecurityContextHolder doesn't contain a SecurityContext with an authenticated Authentication, AND the request contains user credentials, then register a new user and fill the SecurityContextHolder with a SecurityContext for the newly registered user. After the login controller action returns, control goes back up the security filter chain and the filter upstream from your custom filter will generate a token based on the Authentication object that you provided.

Please keep in mind that this suggestion is based on a very big assumption. We can provide better support if you tell us what middleware is responsible for the token generation.
 
Saloon Keeper
Posts: 23774
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Some day I really ought to study Spring Security in detail, but I have been under the impression that it can (at least sometimes) build on JEE standard container security.

When that is the case, the webapp server (container) compiles all the URL security patterns in web.xml as part of deployment and thereafter, every incoming http(s) request is checked against that set of patterns. The process is as follows.

If the URL matches a protected resource, and the user has not previously logged in then the first thing that happens is that the webapp server sidetracks the request and demands authentication (login). If, only if, and when the user has authenticated with the container (via dialog or form-based authentication), then the sidetracked request URL is checked to make sure that the authenticated user has been assigned security roles that match that URL pattern, Failure to do so will cause the webapp server to return a "403 - Forbidden" result.

If the user has passed the necessary tests, then - and ONLY then - does the request get passed to the actual webapp. At which point Spring Security's own unique abilities can be applied on top of the container security. At this point I'll have to leave you to other experts, but the point is that container security (when used) is the first line of defense against malicious attacks and since absolutely no application code is involved, that means that security holes in the application itself cannot be exploited at that level.

What Stephan says about Spring Security within the app is in the same vein - block first, and only allow stuff that's permitted through to the application business logic. Good security systems are almost completely transparent to application logic.
 
Nmeri Alphonsus
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry, man about my response time. I've been slugging it out with getting the authentication up and running.

Stephan van Hulst wrote:
No, you really should not be doing anything security-related in your controllers. That's what the security filters are for.


Yes, you are correct. I come from a framework where authentication is clearly spelt out in its controllers, but suddenly realized Spring works differently and is done at a place where request parameters aren't even available

Stephan van Hulst wrote:
How are the JWTs generated? Are you using one of the standard security filters, or did you insert a third-party filter into the filter chain?


I am using the package com.auth0.jwt like so



Stephan van Hulst wrote:
If the filter that generates the JWT generates a token based on the SecurityContext provided by filters further down the chain, then you can solve this problem pretty easily: Just add a custom security filter at the end of the filter chain that does the following:

If the SecurityContextHolder doesn't contain a SecurityContext with an authenticated Authentication, AND the request contains user credentials, then register a new user and fill the SecurityContextHolder with a SecurityContext for the newly registered user. After the login controller action returns, control goes back up the security filter chain and the filter upstream from your custom filter will generate a token based on the Authentication object that you provided.

Please keep in mind that this suggestion is based on a very big assumption. We can provide better support if you tell us what middleware is responsible for the token generation.



Ha! I haven't even had the need to work with multiple filters yet. I am still grappling with other variations of the flow in my OP. Although as I write this, I've been able to access my custom filter (only by supplying it via a method rather than instantiating it in the SecurityConfig::configure method). I don't know what lies ahead of that yet, but your solution sounds plausible as pseudo-code. None of the articles I've seen online work directly with SecurityContext. In fact, one of them claims using it to retrieve users in the controller is an outdated method

In retrospect, I think the clunky procedure described earlier will be sufficient for the SPA I'm working on. The client can visit multiple endpoints in the background without it seeming weird
 
Nmeri Alphonsus
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Some day I really ought to study Spring Security in detail, but I have been under the impression that it can (at least sometimes) build on JEE standard container security.


I understand that flow. I'm asking more of in the context of my problem, not necessarily whether security should live in controllers or not. I:

  • Want to use the same endpoint to serve login and registration functions
  • Have additional fields (that don't include a password btw)


  • I would easily have posted the code I have already but was deterred by the fact that something as simple as user retrieval can be made convoluted enough to span multiple objects. Let's see. In my SecurityConfig, I have



    Next in line is JWTWithoutPasswordFilter


    Meanwhile, we have the following on CustomAuthenticationProvider. I haven't been able to run it yet, cause my JSON payload keeps failing to get parsed by the ObjectMapper in the main filter
     
    Tim Holloway
    Saloon Keeper
    Posts: 23774
    161
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    In the case of container-managed security, the "endpoint" (authentication and authorization) is both defined and handled solely by the container. The only choice the app itself has is to specify which type of authentication front-end (dialog or form) will be used, and technically, the web.xml file is considered a (server-independent) deployment descriptor rather than strictly application code.

    The actual security mechanisms in container security are defined via plug-replaceable components configured into the webapp server (using the other (server-dependent) deployment descriptor. Thus I can use an XML file for testing and LDAP and/or a database for production without rebuilding the webapp.

    Aside from this complete isolation between security application and administration (i., e., creating/updating accounts, there's another good reason for keeping account maintenance out of the application. When you're using, for example, a database as your A&A reference and allowing it to be updated within your webapp, that means that the entire webapp has potential access to a database connection pool with greatest-common-denominator access to both business and security data from any user. Instead, I highly recommend using a separate webapp (or other channel) to maintain the A&A data.

    Indeed, it's common in large enterprises for the security profiles to be created and maintained solely by a security management group and there would be no purpose in letting them into your business logic any more than there would be to allow a user to be able to potentially enable themselves to unrelated apps in a shared security environment.

    Note that I do draw the distinction between security profiles and user profiles (preferences). User profiles tend to be per-application, and shouldn't have anything in them that allows privilege escalations.

    There is of course, a difference between internal security and external application users. If I'm setting up the next Amazon.com, I do want new users to be able to register accounts and maintain (within limits) their security options. And there are industry best practices for that kind of stuff, but it's not specific to Spring Security.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 13014
    281
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    None of the articles I've seen online work directly with SecurityContext. In fact, one of them claims using it to retrieve users in the controller is an outdated method


    Yes, but we're not using it to retrieve the current user from the controller. We're using it to set the current authentication.

    I would easily have posted the code I have already but was deterred by the fact that something as simple as user retrieval can be made convoluted enough to span multiple objects.


    You really should make use of the fact that it allows you to solve different parts of the authentication process in different classes. In particular, I would dissuade you from extending UsernamePasswordAuthenticationFilter and suggest that you implement AbstractAuthenticationProcessingFilter. It would look roughly like this:

    Plug in an UserNameAndOtpOrNewRegistrationAuthenticationManager that checks that checks that the authentication type is UserNameAndOtpAuthentication and uses the user name and OTP to authenticate the user. If the user exists but could not be authenticated, throw a BadCredentialsException. If the user does not exist, simply register them. Finally, generate a token based on the authenticated user (whether existing or new) and return it in a new JwtAuthenticationToken.
     
    Nmeri Alphonsus
    Greenhorn
    Posts: 7
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:

    In the case of container-managed security, the "endpoint" (authentication and authorization) is both defined and handled solely by the container. The only choice the app itself has is to specify which type of authentication front-end (dialog or form) will be used, and technically, the web.xml file is considered a (server-independent) deployment descriptor rather than strictly application code.

    The actual security mechanisms in container security are defined via plug-replaceable components configured into the webapp server (using the other (server-dependent) deployment descriptor. Thus I can use an XML file for testing and LDAP and/or a database for production without rebuilding the webapp.


    Wow! This is actually beautiful. Although the alternative in the framework I come from works, this makes sense as it's not a core business concern. On the other hand, one can argue that by virtue of customizing authentication to suit business needs, it automatically becomes a business concern and should reside amidst such objects

    Tim Holloway wrote:
    Aside from this complete isolation between security application and administration (i., e., creating/updating accounts, there's another good reason for keeping account maintenance out of the application. When you're using, for example, a database as your A&A reference and allowing it to be updated within your webapp, that means that the entire webapp has potential access to a database connection pool with greatest-common-denominator access to both business and security data from any user. Instead, I highly recommend using a separate webapp (or other channel) to maintain the A&A data.

    Indeed, it's common in large enterprises for the security profiles to be created and maintained solely by a security management group and there would be no purpose in letting them into your business logic any more than there would be to allow a user to be able to potentially enable themselves to unrelated apps in a shared security environment.

    Note that I do draw the distinction between security profiles and user profiles (preferences). User profiles tend to be per-application, and shouldn't have anything in them that allows privilege escalations.

    There is of course, a difference between internal security and external application users. If I'm setting up the next Amazon.com, I do want new users to be able to register accounts and maintain (within limits) their security options. And there are industry best practices for that kind of stuff, but it's not specific to Spring Security.



    I don't really get the quoted part, but I kind of disagree with an implementation as drastic as delegation to a separate ap and database
     
    Tim Holloway
    Saloon Keeper
    Posts: 23774
    161
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Let's see if I can put it more simply.

    First, if A&A is entirely container-managed, then the application has no need to access the userid/password/roles database, because those functions are done exclusively by the webapp server itself with absolutely no application logic.

    Regardless, a Database Connection Pool serves up identical Connection objects. That means that any Connection returned from the pool has the same access rights as any other connection in the pool. And if your webapp can maintain security tables, then that means that the Connections can be used interchangeably to read and alter security information.

    So if someone finds a suitable exploit, they'll be able to pwn your entire security database.

    Put the security maintenance in a separate webapp and you can throttle down access to security tables (or omit it entirely) in the application webapp and thus block exploitation at the source, just as container authorization blocks bad URL requests before they can do damage.

    Access to the security maintenance app can be limited to avoid exposure. For example, it might be LAN-only versus the general Internet for the business application.
     
    We cannot change unless we survive, but we will not survive unless we change. Evolving tiny ad:
    Thread Boost feature
    https://coderanch.com/t/674455/Thread-Boost-feature
    reply
      Bookmark Topic Watch Topic
    • New Topic