- In the context of computing, there are many levels of security:
- Hardware Security - prevent unauthorized code execution
- Operation System - access to the computer and action you can take
- Database - access to the database and actions you can take
- Message Brokers - read/write access to message queues
- Network Security - wifi, VPCs, etc
- Application Security - Access to the application and actions within application
- Spring Security focuses on Application Security
- Spring Security does not address other levels of security
- Application Security focuses on who can do what within the context of an application
- Spring Security provides:
- Protection from common security exploits
- Integration with external security products, such as LDAP
- Provides utilities for password encoding
- Identity - A unique actor, typically an individual aka user
- Credentials - Usually a user id and password
- Authentication - Is how the application verifies the identity of the requestor
- Spring Security has a variety of methods for Authentication
- Typically the user provides credentials, which are validated
- Authorization - Can a user perform an action?
- Using the user's identity, Spring Security determines if they are authorized to perform action
-
Authentication Provides - verify users identities
-
Authentication Providers supported by Spring Security:
- In Memory
- JDBC/Database
- Custom
- LDAP/Active Directory
- Keycloak
- ACL(Access Control List)
- OpenID
- CAS
- Spring Security supports a variety of methods to store an verify passwords
- NoOp password encoder - plain text, not recommended
- BCrypt - uses bcrypt password hashing
- Argon2 - Uses Argon2 algorithm
- Pbkdf2
- SCrypt
- Core - Core modules of Spring Security
- Remoting - Only needed for support of RMI operations
- Web - Support of web applications
- Config - Provides support for XML and Java configuration
- LDAP - for integration with LDAP identity providers
- OAuth 2.0 Core - Core of OAuth 2.0 Authorization and OpenID
- OAuth 2.0 Client - Client support for OAuth 2.0 and OpenID clients
- OWASP - Open Web Application Security Project
- Injection - Injection of malicious code, such as SQL Injection attacks
- Mitigation typically using proper encoding and bind variables
- Broken Authentication - Authentication and session management implemented incorrectly
- Mitigation - Use framework, don't roll your own
- Sensitive Data Exposure - Not protecting sensitive data
- Mitigation - Proper error handling, don't expose stack traces
- XML External entities - Poorly configured XML processors
- Mitigation - Patch XML Processors frequently
- Broken Access Control - User Restrictions not properly enforced
- Mitigation - Automated Testing, verify restrictions
- Security Misconfiguration - Unintentionally not protecting resources
- Mitigation - Security Audits
- CrossSite Scripting - XSS Allows Users to inject HMTL or javascript
- Mitigation - Use proper validation and escaping
- Insecure Deserialization - Insecure deserialization can allow remote code execution
- Mitigation - Use open source, patch frequently
- Using Components with Know Vulnerabilities - Popular components often have known vulnerabilities
- Migigation - Patch frequently
- Insufficient Logging and Monitoring - Time to detect breaches often over 200 days
- Mitigation - Properly monitor systems
- Spring Security has built in support to address several common vulnerabilities
- Cross-site Scripting (XSS)
- Cross-site Request Forgery (CSRF)
- Security HTTP Response Headers
- Variety of headers can be set to improve browser security
- Redirect to HTTPS
- User enters text in an input field, within text is javascript code
- Server accepts text without encoding or sanitizing
- User enter text displayed to user on page, JavaScript code executes
- Entered text should be scrubbed of JavaScript characters
- Special characters should be HTML encoded
- For complete precautions refer to OWASP
- Header
X-XSS-Protection
is set to1; mode=block
- Tells browser to block XSS code when detected
- Modern Browsers are starting to deprecate this in favor of Content Security Policy
- Content Security Policy - Spring Security does not implement a default value
- Spring Security can easily be configured
- A Cross-Site Request Forgery (CSRF) attack is when a site tricks the user's web browser to send a request to a cite where the user is authenticated
- CSRF attacks work because the browser is tricked into sending session cookies to the trusted site
- Thus, the trusted site cannot distinguish the request is not form the authenticated user
- The Synchronizer Token Pattern requires in addition to the session cookie, a secure random CSRF token must be in request
- CRSF Token must be part of HTTP Request not automatically sent by browser
- Do not store CRSF token is cookies
- Use:
- HTTP Headers
- Hidden Form Fields
- The SameSite cookie attribute can be set to tell browser to not send cookie when request is coming from other sites
- SameSite cookie attribute is supported on all modern browsers
- Supports - None, Lax(~subdomain), Strict
- Modern browsers transitioning from None to Lax if not explicitly set.
- Should not solely rely on SameSite attribute for CSRF prevention
- Spring security Team recommends:
- Use CRSF when request are processed by a browser by normal users
- ie - HTML, Single page apps (Angular, React, etc)
- If only used by non-browser clients, disable CSRF
- ie - programmatic clients, like spring resttemplate or webclient
- Use CRSF when request are processed by a browser by normal users
-
HTTP Basic Authentication is part of the HTTP Specification
- Originally from RFC 2617, 1999, updated in RFC 7617 in 2015
-
Basic Authentication provides a standard way for HTTP clients to submit user name and password
-
URL Encoding -
https://username:password@www.example.com
-
HTTP Header - Key: Authorization, Value: Basic
- String - username:password
-
URL Encoding and Header Encoding are not secure
-
To protect users credentials, use of HTTPS is recommended
-
HTTP Basic Authentication also criticized for sending user credentials in every request
- Increases risk of compromise
- Other methods send an authentication token in each request
- When Spring Boot detects Spring Security on the classpath, it will auto-configure Spring Security for HTTP Basic Authentication
- Default User - user
- Set Property spring.security.user.name to override
- Default Password - Random UUID, check console output
- Set Property spring.security.user.password to override
- Default User - user
- All paths secured - except actuator info and health
- Authentication Filter - A filter for a specific Authentication type in the Spring Security filter chain (ie basic auth, remember me cookies, etc)
- Authentication Manager - Standard API interface used by filter
- Authentication Provider - The implementation of Authentication (in memory, database, etc)
- User Details Service - Service to provide information about user
- Password Encoder - Service to encrypt and verify passwords
- Security Context - Holds details about authenticated entity
- Implements User Details Service
- Used by Spring Boot Auto-configuration
- Non-persistent implementation - uses in memory map
- Mainly used for testing and demonstration purposes
- Not normally used in production systems
- When logging in, the application needs to verify the entered password matchers the password value stored in the system
- Legacy systems sometimes store passwords as plain text
- Obviously not ideal
- Other systems encrypt the password in the database, then decrypt to verify
- Again not ideal - can be decrypted to original value
- A hash is a one-way mathematical algorithm applied to the password
- One way meaning the hash value can be generated from a password
- But the password cannot be generated from the hash value
- Example
- password: password 1
- hash value: 5f4dcc3b5aa765d61d8327deb882cf99
- In this theoretical example, the stirng
password 1
will always hash tohash value
- Problem where hash functions generating known hash values
- Became a dictionary attack to guess passwords from hash value
- Solution is to use a salt value
- A salt is additional data added to the value being hashed
- Example of password with salt: password1{ThisIsMyReallyLongPasswordSaltValue}
- Modern algorithms use random salt values
- Thus hash value changes each time
- The security area of Hash functions is effectively an arms race
- As computational power increases, researchers find more vulnerabilities
- Spring Security supports plain text and order hash functions for compatibility with legacy systems
- These encoders are marked as deprecated to warn you they are not recommended for use
- Spring Security 5 introduced a delegating password encoder
- Allows storage of password hashes in multiple formats
- Password hashes stores as - {encodername}
- Thus allows you to support multiple hash algorithms while migrating.
- The Spring Security team recommends using an adaptive one way encoding function such as:
- BCrypt (Default)
- Pbkdf2
- SCrypt
- These are also considered
slow
, which are computationally expensive to guard against brute force attacks
- All Spring Security Filters implement the Filter interface
- Part of the Java Servlet API
- Accepts Servlet Request, Servlet Response, and Filter Chain
- Can be used to implement actions on the Request or Response
- HTTP Basic Authentication is using the filter
BasicAuthenticationFilter
- Inspects Request for HTTP Basic credentials and performs Authentication
- Hypothetically speaking we have a REST API using cutom headers for Authentication
- Goal here is to mimic a legacy application
- Thi is not a recommended approach for Authentication
- Legacy Application sending API key and API Secret in HTTP Headers
- Create a Spring Security filter for this legacy Authentication
- Extend Spring Security's AbstractAuthenticationProcessingFilter
- Configure Spring Security to use Custom Filter
- Using a traditional databse for Authenticatio is amatter of providing an alternate User Details Service
- Spring security provides the interface, you provide the implementation
- Can be in memory, JDBC, NoSQL, external service, tc.
- Spring Security does provide a JDBC implementation with database schemas
- Typically a starting point and then customized to your application
- Provide custom Database Authentication using Spring Data JPA
- Need User and Authority JPA Entities
- Spring Data JPA Repositories
- Custom implementation of User Details Service using Spring Data Repostiories
- Configure Sping Security to use custom imlementation of User Details Service
- Authorization is the approval to perform an action within the application
- Authorization can be as simple as allow all or is authenticated
- Specific actions can be limited to specific roles to authorities
- By default, Spring Security roles start with "ROLE_"
- Example: ROLE_ADMIN
- Spring Security authorities may be any string value
- Typically a role is considered a group of one or more authorities
- In a Spring Security context:
- Roles by default start with "ROLE_"
- Configuration uses methods of
hasRole()
orhasAnyRole()
- requires prefix
- Configuration uses methods of
- Authorities are any string
- Configuration uses methods of
hasAuthority()
orhasAnyAuthority()
- Configuration uses methods of
- Roles by default start with "ROLE_"
- Access Decision Voters provide a vote on allowing access
- ACCESS_ABSTAIN - Voters has no opinion
- ACCESS_DENIED - Voters does not approve
- ACCESS_GRANTED = Voter approves access
- Most commonly used voter in Spring Security
- Uses role names to grant access
- If Authenticated user has role, access is granted
- If no authorities begin with prefix of
ROLE_
this voter will abstain
- If no authorities begin with prefix of
- Grants Access based on level of authentication
- Anonymously - Not Authenticated
- Remembered - Authenticated via Remember me cookie
- Fully - Fully Authenticated
- Accepts list of Access Decision voters
- Polls each voter
- Access granted based on total of allowed vs denied responses
- Allows configuration of Role Hierarchies
- Example:
- ROLE_USER
- ROLE_ADMIN > ROLE_USER > ROLE_FOO
- ROLE_ADMIN will have all of its authorities, and those of ROLE_USER and ROLE_FOO
-
permitAll - Allows all access
-
denyAll - Denies all access
-
isAnonymous - Is Authenticated Anonymously
-
isAuthenticated - Is Authenticated (Fully or Remembered)
-
isRememberMe - Is Authenticated with Remember Me Cookie
-
isFullyAuthenticated - Is Fully Authenticated
-
hasRole - Has authority with ROLE_**
-
hasAnyRole - Accepts list of ROLE_** strings
-
hasAuthority - Has authority string value
-
hasAnyAuthority - Accepts list of stirng authority values
-
hasIpAddress - Accepts Ip Address or IP/Netmask
- Securing specific URLs is done using Spring Security Filters
- Filters use configured voters to determine authorization
- Security expressions available for use in Java configuration of HttpSecurity
- Spring Security also has method level security
- Enable using
@EnableGlobalMethodSecurity
configuration annotation @Secured
- accepts list of roles, orIS_AUTHENTICATED_ANONYMOUSLY
@PreAuthorize
- acceots security expressions- Under convers Spring Security is using AOP to intercept and use the
AccessDecisionManager
- Same technique as Filter
- Update Spring Security for the following
- Prepend ROLE_ to ADMIN, CUSTOMER, and USER
- Require ADMIN ROLE to Delete Beer
- Require ADMIN or CUSTOMER Role for Breweries
- Require ADMIN or CUSTOMER or USER ROle for Find Beer
- Require ADMIN or CUSTOMER Role for list customers
- Require ADMIN for Register Customer
- Current user roles are very broad in scope
- Do not match granularity of application
- How to describe different of access of CRUD type operations
- This problem would only grow in scope with complexity of application
- Solution: Refactor to traditional model of roles with authorities
- User assigend a role, which has a set of defined authorities
-
Multi-tenant software architectures allows multiple users to share a single instance of a software application
-
Tenants are uses, can be individuals or groups
- Individuals - example Gmail
- Groups - example GitHub Organizations
-
Benefit of multi-tenancy is efficiency
-
Multi-tenancy comes in many different forms
-
Shared Databases can use a schema per tenant or shared tables with a tenant attribute
-
When the application and/or database is shared application security needs to prevent unauthorized access
- Customer A should not be able to read Customer B's data
- Customer A should not be able to udpate or delete Customer B's data
- A super user may need access to all customer data
- Service accounts many need access to all customer data
- Use Case: Allow Customers to Place Orders, Read Orders, and Cancel Orders
- A customer can have one or more users
- A custom UserDetails Object is used to hold necessary attributes in Security Context
- SPeL is used to access attributes to make access decisions
- For our use case, we will add Customer to the UserDetails object
- Rather than using the Spring Security User Object, we will implement our own
- The Beer Order Controller exposes endpoints for:
- Create new Beer Order
- List Beer Orders for Customer, Get Order by ID
- Pickup Order - mimics a API transaction to 'pickup' an order
- Update and delete Beer Order not implemented
-
Create Order
- Not Logged in cannot create order
- Admin can create for any customer
- Customer User can create their customer
- Customer User cannot create for a different customer
-
Read Order
- Not Logged in cannot Read order
- Admin can read for any customer
- Customer User can Read their customer
- Customer User cannot read other customers
-
Pickup Order - API transaction for Customer to 'pickup' an order
- Not Logged in cannot pickup order
- Admin can Pickup for any customer
- Customer User can Pickup their customer
- Customer User cannot Pickup other customers
- Spinrg Security provides a tag library for working with JSP Templates
- Thymeleaf provides a tag library with feature parity for Thymeleaf templates
- Features and functionality are the same between JSP and Thymeleaf
- We will focus on Thymeleaf examples
- Requires dependency org.thymeleaf.extras:thymeleaf-extras-springsecurity5
- Add namesapce:xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
- Spring Security Expression methods in SPel exposed - ie hasRole(), hasAnyAuthority(), etc
- Authentication object available - implementation of Spring Security Authentication interface
- Tag sec:authentication="xxxx" - outputs value of named property
- Tag sec:authorize="expr" or sec:authorize-expr="expr" - renders element based on SPeL expression
- Tag sec:authorize-url="url" renders element if user is authorized to view url
- Tag sec:authorize-acl="object::permissions" renders element based on ACL permissions
- In this seciont we will add a login form to the index page
- Configure Spring Security to use Login form
- Show login form if not logged in, redirect to login form on unauthorized access
- Hide login form and show logout link if logged in
- Update Application to show or hide menu options and buttons based on user permissions
-
Remember Me is a technique of allowing a web application to
remember
the login details of a user -
Allows user to stay signed into web application, without having to login again
- Logins in Java are typically tracked with a session id, which is short lived
-
Remember Me is implemented by storing user details in a cookie
- Application uses cookie details to authenticate user upon their return
- Cookie can be set to expire after X period of time
-
Remember Me is typically done by user opt-in
- User should not use Remember Me on public computers
- Should not be done automatically
- Data in Remember Me is used to authenticate
- If compromised, the Remember Me cookie could be used to impersonate the user
- Effectively a username and password rolled into a cookie
- Best practive is to never send Remeber Me cookies over HTTP
- Always use HTTPS to protect cookies from third parties
- Due to potential compromise of Remeber Me Cookies, sensitive funcitons should be restrcited
- Spring Security has methods for
isRemmebered
orisAuthenticatedFully
- Require full authentication for functions such as:
- Password change
- Email change
- Update of personal information - name, address, payment information, etc
- Making purchases
- Spring Security provides two remember me implements
- Simple Hash-Based Token
- Persitent Token
- Both implementations required a UserDetailsService
- Not all authentication provides have a UserDetailsService
- For example, LDAP
- Not all authentication provides have a UserDetailsService
- The Simple Hash-Based Token is a Base64 string consisting of:
- base54(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
- The advantage of having the password in the hash in the user can change their password and invalidate all remember me tokens
- Can support multiple browswers/computers
- Attacker can use cookie until it expires or password is changed
- Remeber Me Cookie contains: username, a series id, and a token (random string)
- These values are persisted to the database
- On login via Remember Me valuse are fetched from database
- If matched, user is authenticated, and new token is created for series id (browswer/devices)
- If username and series match, but token does not, theft is assumed
- Delete all tokens for user
- Shortens attack window until real user logs in vs expirationTime
- From Drupal CMS
-
Spring Security will send an Authentication Success or Authentiaction Failuer Event with every Authentication Attempt
-
These events are important hooks for monitoring system access
-
Can be used for:
- Logging who logged in when and from where
- Failed log in attempts
- Automatically lock accounts for too many attempts
-
Spring Security Authentication Events use the Event functionality found in Spring Framework
-
Publish / Subscibe Type of Model
- Spring Security will publish the event
- One or more listeners can register to receive the event
-
Available in all Spring Security Provided Authentication Providers
- You are responsible for event publishing if using custom provider
- BadCredentialsException = AuthenticationFailurebadCredentialsEvent
- UsernameNotFoundException = AuthenticationFailureBadCredentialsEvent
- AccountExpiredException = AuthenticationFailureExporedEvent
- ProviderNotFoundException = AuthenticationFailureProviderNotFoundEvent
- DisabledException = AuthenticationFailureDisabledEvent
- LockedException = AuthenticationFailureLockedEvent
- AuthenticationServiceException = AuthenticationFailureServiceExceptionEvent
- Spring Security can be configured additional or custom Authentication Events
- Provide own instance of AuthenticationEventPublisher
- Customize as needed
- Provide own instance of AuthenticationEventPublisher
- Two Factor Authentication is a type of multi-factor authentication
- Also called 2FA
- 2FA Authentication requires the user to present two or more authentication factors
- Goal is to prevent unauthorized account access from account password being compromised
- Could be as simple as username, password, and code sent via text message
- Thus, user needs to know password and have device receiving text message code
- 2FA should use two different Authentication factors
- Something You Have - A bank card, a USB Key with code (like Yubikey), FOB with code
- Something You Know - Knowledge of the user - password, PIN, Security question
- Something You Are - Biometric - fingerprint, iris or face scan
- Somewhere You Are - A location physical, or GPS based
- Time-Based One-Time Password - Unique code, valid for ~30 seconds
- aka TOTP
- Adopted by Internet Engineering Task Force (IETF) under RFC 6328
- Algorithm based on Unix time
- Integer of seconds since January 1, 1970 (dropping any leap seconds)
- Uses a shared
secret
, which if compromised will allow attacker to generate codes
- Open Source TOTP generator for Android or iOS
- Allows user to easily setup TOTP via scanning a QR Code
- QR Code generated using
- Label - Account Name(username)
- Secret - Arbitrary key value Base 32 encoded (shared secret, should be protected)
- Unique to user
- Issuer - Organization Issuing TOTP
- Goal - Configure Spring Security to use Google Authenticator for 2FA
- Google Authenticator Registration:
- Scan QR Code to register application
- Provide User Ability to opt-in to 2FA
- User which have opted into 2FA required to enter 2FA code after login
- User not opted in, do not need to enter code
- Update User Entity to hold:
- Use 2Fa? - Is user registered for 2FA
- 2FA Secret - Shared Secret with Google Authenticator
- 2FA Required? - Transient Property to require entering of 2FA code
- Spring Security 2FA Filter
- On Login, If User is 2FA enabled, forward to 2FA Authentication URL
- Add Menu Option and page to Enable 2FA
- Controller will update User with 2FA secret and show QR code
- Accept Form Post of TOPT code from Google Authenticator
- If valid, enable 2FA for user
- Redirect to index
- Accept username password as normal
- If user is 2FA enabled forward to 2FA verification page
- Use Spring Security Filter for forward
- Filter will restrict user to verfication page until proper code is entered
- Example intentionally for Spring MVC, will word for most typical web applications
- Not following TDD - well covered, typical unit testing
- Not covering user registration - little Spring Security needed
- Traditional Spring MVC application
- Single Page Javascript could be adopted to this example
- ie. Angular, ReactJs, etc
-
What worked well?
- wsstrange GoogleAuth library
- Google Authenticator
- Spring Security Filter and Failure Handler
- 2FA Optional, enforced when enabled
-
What worked could be improved?
- UI Formating
- Testing
- Hide 2FA Option once enabled
- Add other 2FA options such as text or email
-
Cross-Origin Resource are common in web applications
-
A typical web page may use Cross-Origin Resource for:
- Images/videos
- Content Delivery Network (CDN)
- Web fonts
-
Some Cross-Origin Requests are forbidden (mainly Ajax)
-
CORS is a standard to enable Cross-Origin Requests when needed
-
CORS is a browser standard, it is the browswer impelementing the security restrictions
- Server provides data, browswer implements
-
Browswer displaying page from
myapplication.com
, Javascripts makes request fromapi.myapplication.com
- Browswer performs HTTP GET at
api.myapplication.com
; with HTTP HeaderOrigin:myapplication.com
- Browswer performs HTTP GET at
-
Server Responds with header
Access-Control-Allow-Origin:myapplication.com
- This indicates the api domain can be accessed from root domain
- Can be
asterisk(*)
- wildcard for all domains
-
An Example of this could be:
- a ReactJS application running at
myapplication.com
- Spring Boot application running at
api.myapplication.com
- a ReactJS application running at
-
Request Headers:
- Origin
- Access-Control-Request-Method
- Access-Control-Headers
-
Response Headers:
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
- Access-Control-Expose-Headers
- Access-Control-Max-Age
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Browswers can also do a
preflight
- A check to see if action is allowed
- Browswer makes a HTTP OPTIONS request using request headers for method and/or headers
- Server responds with HTTP 204 if okay, error if not
- Spring MVC / WebFlux
- Majority of CORS support is built into Spring MVC / WebFlux
- Configuration can be very granular
- Spring Security
- Works in conjunction with Spring MVC / Webflux
- Alternatively can Intercept requests in security filter chain