Spring Boot Security and OAuth2 Udemy - vidyasekaran/current_learning GitHub Wiki

This document is created based on the Udemy couse - spring Boot Security and Oauth2 by Siva Prasad Valluru

Other sites checked:

https://feedly.com/i/entry/jh/tWgMv2e4LXH4Ug1u0iurbUN6OLYq5FbGaLIjyqb4=_165ae79cc39:a6d3ee:3097813d https://oauth.io/

UnderStanding Spring Security and how it uses its filters

1.Request comes to Dispatcher Servlet and routed there but we want to handle user login much before that so spring security uses Filters.

2.There are many filters takes care of each aspect as such Authentication, Authroziation, cross site request forgery, remeber me functionality - a chain.

  1. There are chain of such filters each can be used to 1.google auth 2. github auth etc..

  2. In spring security DelegatingFilterProxy ------- delegates to -----> FilterChainProxy ------delegates to -------> Chain of filters (Authentication, Authroziation...)

  3. Principle is a logged in device or user , this Principle object is created once user is sucessfully authenticated which contains logged in user.

  4. One Principle can have multiple authorities. We can think Authorities as Roles.

  5. Spring Security uses "Principle" and "Authorities" to construct "Authentication" object.

  6. Security Context holds "Authentication" object.

  7. HttpSession hold the "Security Context" object.

  8. Once User is created only Step 5 to 9 happens...

  9. One of the "chain of filters" ---Checks the SecurityContext present in httpsession and ensures user is logged in.

Flow

DelegatingFilterChainProxy ----------> FilterChainProxy ----> Chain of Filters ----> "Dispatcher Servlet" ----->

Securing an application

  1. In pom.xml add "spring-boot-starter-security" and restart app - applcation will print "password on console" and restart application. the app will redirect you to login page where you will need to provide username and password to login.

login : user password : password got when app restarted

  1. I dont want random user name and password - Add below config in application.yml

spring: security: user: name:siva password:secret

#1. Spring Security filters and flow when user trying to access an UnSecured Resource prior to login

The flow in and flow out from 1 to 6 and 6 to 1 performing some activity at each stage.

  1. SecurityContext Persistence filter- 
     Flow In - will there be any Security Context already present? No So Create empty SecurtyContextHolder and set in SecurityContext
             Flow out - Check if the SecurityContext is unmodified if yes removes SecurityContext
    
  2. logout filter - checks if its a logout request? no
    
  3. Authentication Filter - checks if this is an authentication request?
    
  4. Remember me Filter - checks if this is a remember me request?
    
  5. Exception Translation Filter - checks if this is an exception translation filter?
    
  6. Filter Security Interceptor  --> flow in - checks resource to figure auth required if no  allows acccess.
    

#2. User trying to access Secured resource prior to login

In this Scenario the action occurs while control flow return backward

  1. SecurityContext Persistence filter- Flow In - will there be any Security Context already present? No So Create empty 		SecurtyContextHolder and set in SecurityContext.
                                        Flow out - Check if the SecurityContext is unmodified if yes removes SecurityContext
    
  2. logout filter - Flow in -  checks if its a logout request? no
    
  3. Authentication Filter - Flow in - checks if this is an authentication request?
    
  4. Remember me Filter - Flow in - checks if this is a remember me request?
    
  5. Exception Translation Filter - Flow in - checks if this is an exception translation filter?
     	              Flow out - Authentication Entry redirects to login page.
    
  6. Filter Security Interceptor  --> flow in - checks resource to figure auth required - Yes, since
    user is not authenticated - it throws AuthenticationException.
    

NOTE: Since user is not logged in an trying to acess secured resource - "Filter Security Interceptor" throws AuthenticationException and "Exception Translation Filter" redirects it to Login Page.

3. User Submitting login credentials

In this Scenario the action occurs while control flow return backward

  1. SecurityContext Persistence filter- 
     Flow In - will there be any Security Context already present? No So Create empty SecurtyContextHolder and set in SecurityContext
             Flow out - Check if the SecurityContext is unmodified if yes removes SecurityContext
    
  2. logout filter - Flow in -  checks if its a logout request? no
    
  3. Authentication Filter - Flow in - checks if this is an authentication request? Yes - > Now Authentication filter tries to authenticate request by delegating request to a bean "Authentication Manager" ( takes care of authentcation manager). Authentication filter creates an "Authentication" object and tries to invoke AuthenticationManager  which takes Authentication object as input.
    

Authentication Object created by "Authentication Filter" - prior to invoked AuthenticationManager

Authentication request

class Authentication Authenticated: False Principle:Username Credentials:Password Authorities:

Authentication Object after it is authenticated by AuthenticationManager

Authentication principle

class Authentication Authenticated: True Principle:Username Credentials: Authorities:Roles e.g. ADMIN

https://docs.spring.io/spring-security/site/docs/4.2.19.RELEASE/apidocs/org/springframework/security/core/Authentication.html

    public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority>	getAuthorities() - Set by an AuthenticationManager to indicate the authorities that the principal has been granted.
Object	getCredentials() - The credentials that prove the principal is correct.
Object	getDetails() - Stores additional details about the authentication request.
Object	getPrincipal() - The identity of the principal being authenticated.
boolean	isAuthenticated() - Used to indicate to AbstractSecurityInterceptor whether it should present the authentication token to the AuthenticationManager.
void	setAuthenticated(boolean isAuthenticated) - See isAuthenticated() for a full description.
   } 

    public interface AuthenticationManager {
    	Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

3.a. AuthenticationManager doesnot authenticate user instead it sends the request to "Authencation Provider" and this authication provides does the authentication -- it invokes "UserDetails Service" by calling loadUserByUsername -- returns UserDetails -- its an interface - where we need to configure any of the bean such as InMememoryUserDetails or JdbcUserDetailsManager, LdapUserDetailsManager.

3.b. Authentication Filter once it comes 3.a. It loads the SecurityContext with "Authentication Object" which is populated with principles and authorities and "Authentication Object" is stored in Thread Local so that current thread can access it.

  1. Remember me Filter - Flow in - checks if this is a remember me request?
    
  2. Exception Translation Filter - Flow in - checks if this is an exception translation filter?
     	              Flow out - Authentication Entry redirects to login page.
    
  3. Filter Security Interceptor  --> flow in - checks resource to figure auth required - Yes, since
    user is not authenticated - it throws AuthenticationException.
    

NOTE: Since user is not logged in an trying to acess secured resource - "Filter Security Interceptor" throws AuthenticationException and "Exception Translation Filter" redirects it to Login Page.

4. User is trying to hit secured Resource after login with Required Role

In this Scenario the action occurs while control flow return backward

  1. SecurityContext Persistence filter- 
     Flow In - Is there be any Security Context in session already present? Yes So it 
    

fetches SecurityContext and keeps it in SecurtyContextHolder and it stores it in current "ThreadLocal". So that services present across different layers "BusinessLogicLayer", "DataAccessLayer" can access "ThreadLocal". when ever we want securitycontext we can use it from SecurityContextholder.getSecurityContext() looks into "ThreadLocal"

  1. logout filter - Flow in -  checks if its a logout request? no
    
  2. Authentication Filter - Flow in - 
     	       Flow out -
    
  3. Remember me Filter - Flow in - checks if this is a remember me request?
    
  4. Exception Translation Filter - Flow in - checks if this is an exception translation filter?
     	              Flow out - Authentication Entry redirects to login page.
    
  5. Filter Security Interceptor  --> flow in - Logged user access try accessing page which needs login role.
     			checkes logged in user has admin role --> to check this it invokes
    

    AccessDecisionManager -- checks admin role and filter security interceptor grants present access is allowed.

5. User is trying to hit secured Resource after login without Required Role i.e Admin

In this Scenario the action occurs while control flow return backward

  1. SecurityContext Persistence filter- 
     Flow In - Is there be any Security Context in session already present? Yes So it 
    

fetches SecurityContext and keeps it in SecurtyContextHolder and it stores it in current "ThreadLocal". So that services present across different layers "BusinessLogicLayer", "DataAccessLayer" can access "ThreadLocal". when ever we want securitycontext we can use it from SecurityContextholder.getSecurityContext() looks into "ThreadLocal"

            Flow out - 
  1. logout filter - Flow in -  checks if its a logout request? no
    
  2. Authentication Filter - Flow in - 
     	       Flow out -
    
  3. Remember me Filter - Flow in - checks if this is a remember me request?
    
  4. Exception Translation Filter - Flow in - checks if this is an exception translation filter?
     	              Flow out - Authentication Entry redirects to login page.
    
  5. Filter Security Interceptor  --> flow in - Logged user access try accessing page which needs login role.
     			checkes logged in user has admin role --> to check this it invokes
    

    AccessDecisionManager -- checks admin role is present since logged in user doesn't have admin role it throws AccessDeniedException and filter security interceptor grants present access is denied.

OAUTH2


If u access Quora it will ask you to login using "google", if i provided google login id and password then quora will read my mails also that i dont want.

Oauth2 is a protocol that allows a resource owner to grant partial authorities to a client application to access resources in google or facebook etc.

without granting full credentials.

This is like providing a valet key instead of orignal key to a driver to park a car because "with a valet key a car can travel only 1 or 2 kms". some valet key wont allow to open trunk. so with valet key we give restricted access to car. In the same way we give restricted access to an application to access our resources.

We have 4 actors in Oauth2 - Resource Owner, Authorization Server, Resource Server, Client App (ex: quora, who wants access to our resources). 4 GRANT TYPES IN OAUTH2 - Authorization Code grant, Client credential grant, resource owner password grant, implicit. **If Quora wants to continue with google then Quora will registered with google and get CLIENT_ID and SECRET. Qurora is client here so it has to give google the redirect URI where google will redirect after sucessful authentication of resource owner.

Quora also wants to access Resource Owners Google details as resource owner is using google credentials to login Quora to enable this during registration with Google,** quora need to tell google the Permissions or Scopes required ** Example of Scope : Read Contact, read photos ... So the authorization server (google) knows the Permission on which resources the application (Quora) want.

So think quora implmented spring security - now when a resource owner tries to access Quora - one of the spring security filter redirects client request to Google (Authorization server).

**Steps **

  1. User clicks on quora
  2. Quora redirects to google
  3. Resource owner submits credentials and credentials correct
  4. google present a consent page to us where you are willing to consent or scope or permission to the client app (grant partial authorities) Google then generates "auth code" and may store detais like this **"auth_code" is provided to quora with what scopes the resource owner now granted ** permission
  5. Google auth server redirects it to redirect URL provided by Quora during registration.
  6. quora cannot access resource server with just "auth_code" it needs "ACCESS TOKEN".
  7. To get "ACCESS TOKEN" from Authorization Server (google auth server) , quora application send "auth_code", "client_id", "secret" to google auth serer and gets "ACCESS_TOKEN" from Authorization Server.
  8. Using "ACCESS_TOKEN" quora "requests for profile" to resource server.
  9. Resource Server need to figure out details of this "ACCESS_TOKEN" so it send this "ACCESS_TOKEN" to authorization server and gets details of the User in JWT format to whom this "ACCESS_TOKEN" is granted.
  10. Now quora Client gets the profile of the user got from authorization server from Step 9, this user profile will have users name, phone number, full name , last name -> quroa (if uses spring security) creates principle object - assign authorities, populate authentication object, set it in security context, put the security context in session. If security context present in session it means user is logged in.

NOTE: Here quora is getting the "ACCESS_TOKEN" by passing the "auth_code" so this grant type is called "Authorization Code Grant" also called OAuth dance

  1. Oauth2 is a protocol which allows access to grant limited access to their resources on one site to another site without having to expose their credentials. I don't want to give Quora full access to read everything from google example my google mail, i want to give partial access to Quora on google. I can just authorize or Grant Quora to read at least my contacts so.....OAUTH2 is a protocol that allows resource owner to provide partial authorities to retrieve a resource without giving full access.

Example: Many luxury car comes with valet key which allow driver to drive 1 or 2 kms to just park, cannot open car trunk. so we give restricted access. Same like this we give restricted access to google not full access.

4 GRANT TYPES IN OAUTH2

  1. Authorization code grant.
  2. Client credential grant.
  3. Resource Owner password grant.
  4. Implicit code grant

We now see "Authorization code grant"

  1. We have 4 actors

a. Resource Owner b. Client application (who want access to our resources) c. Authorization Server d. Resource Server

Example: If you want to access Quora you need not register but authentication via Google, Quora will take your authentication or you profile from Google. Quora is a client application who want to access our google detail. Quora internally uses authorization code grant. 1st Quora needs to register with Google Authorization Server informing Scopes i.e permissions that it need it can be to access "Google photos" or "Google Contacts" upon registration Google Authorization which provide clientid and client secret, redirect uri (used by google to redirect upon successful authentication. After this registration process Quora can provide a link to login via google authentication. If Quora uses Spring Security with its filter when user login it redirects to google URL

  1. am a user having google account - google has multiple resource servers each exposing a resource example; google contacts, google photos etc.

              Resource Owner -----------------> Resource Servers Exposing ----------------> Resources (google photo, contact etc.)
    
                                                Authorization Server 
    

Flow.

  1. Quora provides a link and user click on the link.

  2. Link redirects him to login page of google authentication. (think Quora uses spring security)

  3. User submits with correct credentials

  4. Google shows a page to user and seek accept Scopes or users permission saying the client app wants access to such and such and you are ready to authroze?? If user submits ok google understand it want to provide client app a partial access.

  5. Google generates "AUTHORIZATION CODE" or "AUTH CODE". Google stores this auth code is given to which client and for what scopes granted by resource owner and Redirect to client with auth code (redirect to an url set during registration time by client app owner). with just this "auth code" client cannot access resources in resource server.

  6. Client App "Request Access Token " to Google Authorization Server, client app sends Auth code, Client Id and Client Secret to Google Authorization server and gets Access token

  7. google authorization server returns access token to client app.

  8. client app sends access token as request to Resource Server - request for profile.

  9. Resource Server validates this "access token" to Authorization Server which upon validation returns JWT TOKEN which contains the details of the user for which this access token is granted.

  10. Resource server provides user profile to client app.

  11. If the client app uses spring security it then creates "principle" , "assign authrorities" , populate into auth object, populate security context and put security context in security context holder and put in thread local. If a security context is present it means user is logged in.

  12. In this Case the Resource Owner is able to login Quora Client App using Google Authenticatin server. The resrouce owner provided partial authorities to the client to retrieve his profile. Here the grants are provided to the client based on "Authorization Code". In this case the client app is getting access code by using access token. this is called Authorization Code Grant. since request is dacing between multiple actors so its called Oauth dance.


Some external useful links from feedly on Oauth2 -

We will compare the four OAuth2 grant types side-by-side.

Every OAuth2 grant type flow has the same goal: To obtain authorization key/access token, which represents a set of permissions, from the user, and perform something on her behalf

https://feedly.com/i/entry/jh/tWgMv2e4LXH4Ug1u0iurbUN6OLYq5FbGaLIjyqb4=_165ae79cc39:a6d3ee:3097813d https://oauth.io/ Achieving this goal is a 2-part flow:

Authorization Code Grant Type Flow

https://feedly.com/i/entry/jh/tWgMv2e4LXH4Ug1u0iurbUN6OLYq5FbGaLIjyqb4=_165ae79cc39:a6d3ee:3097813d

You can easily tell that Authorization Code (3rd from left) grant type flow is the most involved, i.e., it has all 5 steps, and it is also the most secure as the key/access token is only issued to the App (backend), which is well-guarded (Step #5), thus reducing the attack surface of the system.

**Get Access Token **- Acquire the authorization key/access token for the user from the OAuth provider, e.g., Twitter

Use Access Token - Use the authorization key/access token to perform something by calling a protected API endpoint on behalf of the user, e.g., post a tweet

Differences Between OAuth2 Grant Type Flow Diagrams

Every OAuth2 grant type flow differs only in the first part of the main flow:

Get Token Acquisition