This repository is not a complete project. It is a personal learning space for experimenting with Spring Security.
- What is Authentication?
The answer to the question “Who are you?”. The system checks whether a user exists with the given credentials.
- DelegatingFilterProxy
A
DelegatingFilterProxyis registered with the servlet container. When a request arrives, the servlet container invokes this proxy. It retrieves theFilterChainProxybean from theApplicationContextand calls itsdoFiltermethod.
- FilterChainProxy
Chooses the appropriate
SecurityFilterChainbased on the incoming request and executes the filters within that chain via theirdoFiltermethods.
- SecurityFilterChain
Contains the actual security filters. It can be configured to match specific security needs. For example, if a
SecurityFilterChainis configured withhttpBasic,it will include theBasicAuthenticationFilter. If the request matches this chain, the filter attempts to authenticate it.
- ProviderManager(AuthenticationManager)
An AuthenticationFilter implementation delegates
Authenticationobject to ProviderManager for authentication. Delegates the incomingAuthenticationobject to the appropriateAuthenticationProvider. The provider uses aUserDetailsService(orUserDetailsManager) andPasswordEncoderto validate the credentials, and returns an authenticated (or throws an AuthenticationException)Authenticationobject.
- AuthenticationProviders
Authenticate the given
Authenticationobject using aUserDetailsServiceand aPasswordEncoder.
- UserDetailsService
Defines the method
loadUserByUsername(String username)which returns aUserDetailsobject based on the provided username.
- UserDetailsManager
Extends
UserDetailsServiceand provides additional methods for creating, updating, and deleting users.
- PasswordEncoder
Applies hashing to the password, generates salt and compares passwords.
- What is session?
Cached information used to identify a user. The server generates a cookie and sends it to the client. On subsequent requests, the browser sends the cookie back, allowing the server to recognize the user. Server uses that cookie to identify and retrieve the associated user session. Sessions are temporary and expire after a set duration.
- How TLS works?
A bit complex. As I understand it:
- The client sends a handshake "hello" message.
- The server responds with its
public key.- The client generates a pre-master key, encrypts it using the
public key, and sends it back.- The server decrypts it with its
private keyand obtains the pre-master key.- Both sides then derive the same symmetric
master keyfrom the pre-master key.- All further communication is encrypted symmetrically for performance.
- Optionally, the server can generate a
Session Ticketfor resuming sessions without generating a new key on each request.
- SecurityContextHolder and SecurityContext
The
SecurityContextholds the currentAuthenticationobject.SecurityContextHolderstores the context in aThreadLocalvariable, making it accessible throughout the execution of the thread.
- This is the default behavior.
- For async operations,
SecurityContextHoldercan be configured to useInheritableThreadLocal, so child threads inherit the parent’s context.- A global strategy also exists but it is rarely useful I guess.
- CORS
Cross-Origin Resource Sharing is a precautionary mechanism implementd by the browser.
Originconsists of protocol, domain and port insformation.https://domain1.com:111andhttps://domain2.com:111are different origins.https://domain.com:111andhttps://domain.com:222are different origins.http://domain.com:111andhttps://domain.com:111are different origins. If browser dedects that an origin request sent to another origin browser first send apreflight requestto target resource. If target respond with a response which includesAccess-Control-*headers browser decide whether to send the actual request. We can use.cors()method on HttpSecurity object to configure cors in Spring Boot.
- CSRF
Cross-Site Request Forgery is an security attack.
<html> <form action="http://targetsite.com/account/update" method="post"> <input type="text" name="email" value="evil@evil.com" /> <input type="submit" id="submit" /> </form> <script> document.getElementById("document").click(); </script> </html>When user send a GET request to
evil.com, the attacker send that form to victim. Browser redirects to addresshttp://targetsite.com/account/updatewith a email value and the victim's emil is uopdated. CSRF token can be used to prevent the attack. Web application sends a token and check the existance of token for eachPOST,PUT,DELETErequests.
Real owner of the data or service. Consider
Google Photos, as a end user we are the real owner of the photo.Third party app which need to use our resource to give us extra service. For example it can be a
Photo Editorapp which need to use our photos.Server which contains our data and service. In our example Server which contains Google Photo app. When we need to reach our photos we need send a request to that server. The client need to do same action when it needs our photos.
Server which store our(we are Resource Owner) credentials If we want to reach our resource first we need to access that server to get access token. After that we can use application which use that server a Auth Server.
It corresponds to the concept of
authoritiesinside Spring Security. When we need a token we need to tell the server what we want to do with that token. In the example ofPhoto Editorreading the photos is the scope.
Request sent to the Auth Server by Resource Owner. Request includes:
response_type=codeIndicates that the server needs to response aauthorization code.client_id={client_id}Point to the Client in our example it is thePhoto Editorapp. Photo Editor app register itself to the Auth Server once in a lifetime and Auth Server gives it to the ClientID and ClientSecret.redirect_uri={client_address}auth server redirect to client's after process that request.scope=photo+offline_access}indicates that what resource owner wants the client does.state={code_against_csrf}Clientgenerates it and send it to the Auth Server when Auth Server redirects to the Client again it add that code to the request so Client knows it's the own request.Auth Server redirects to the Client with a request and add request parameters.
?state=qvkEJcF3SvmIGqb8&code=-gSCJWIXgohlxIaGw6KyFMD7cA0eGjavPnU-JhYl25RTi0PR
Stateused by client to check it's the own request.Codeis the authorization code. With that code Auth Server knows that the Client can request a access token to access resource which Resource Owner wants to Client access.Client wants a token from Auth Server with a POST request.
grant_type=authorization_codeindicated the flow.client_id=SPT5b6oDVqmwjvkMbuNMVBEaindicates the client.Photo Editor.client_secret=msEM9e-Et9fMUPOtVQXGXBqFCwd-OMy2x5c1i9ZppFkaql2-Client prove itself to the auth server.redirect_uri=https://www.oauth.com/playground/authorization-code.htmlauth server redirects to that address after process post request.code=-gSCJWIXgohlxIaGw6KyFMD7cA0eGjavPnU-JhYl25RTi0PRAuthorization Code which generated by Auth server at the request of Resource Owner. Includes scopes.token end point responses to the Client: { "token_type": "Bearer", "expires_in": 86400, "access_token": "J6q-wAZKSAFF4q_Mgz-bViLT9LQp1nIqPHxONTle66JaxCZTZWliUkHfQyvc8dAjhFyg8_V4", "scope": "photo offline_access", "refresh_token": "fAhatIytgW2eGG24gMdCUunl" } Client can use access_token to reach resource which belongs to the Resource Owner.
- TLS configuration on localhost
- HttpBasic authentication
- FormLogin authentication
- ExceptionHandling configuration
- Custom UserDetailsService
- Custom AuthenticationProvider
- Custom AuthenticationEntryPoint
- Custom AccessDeniedHandler
- JwtToken based authentication implementation
- Social Login With Google Oauth2 Server
- Using Keycloak as Authorization Server
- Spring Security Zero to Master (Udemy)
- Spring Boot ile Rest API Geliştirme (BackendGuru)
- Spring Security Official Documentation
- ChatGPT and DeepSeek 😄
- Java 21
- Maven
- Postman
- Docker
# Run a PostgreSQL container
docker run --name easybankapi-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=easybankapidb \
-p 5432:5432 \
-d postgres
# Clone the repository
git clone https://github.com/cd0b/SpringSecurityTutorial
cd SpringSecurityTutorial/easybank-api
# Run the project
mvn spring-boot:run# Run a KeyCloak container
docker run -d -p 127.0.0.1:3000:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.3.2 start-dev
# Clone the repository
git clone https://github.com/cd0b/SpringSecurityTutorial
cd SpringSecurityTutorial/UsingKeyCloak
# Run the project
mvn spring-boot:run