purpose of SAMLContextProvider in Spring SAML - spring-security

I am trying to understand the flow of sending and receiving Authentication requests in Spring SAML. I noticed that at many points during the process the bean SAMLContextProvider is used. What is its purpose? Can the process work without it?
This bean is referenced on securityContext.xml as:
<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>

The class SAMLContextProviderImpl is one of the important class which plays major role in spring SAML... It decodes and encodes SAML request/response and converts the way spring can understand it. It also makes spring to understand entityId, role, metadata, security keys of an local entity/application ...
Context provider populates information about the local service
provider (your application) such as entityId, role, metadata, security
keys, SSL credentials and trust engines for verification of signatures
and SSL/TLS connections. Once populated context is made available to
all components participating in processing of the incoming or outgoing
SAML messages. ContextProvider can customized to alter behavior of the
SAML Extension. The default implementation
org.springframework.security.saml.context.SAMLContextProviderImpl
relies on information available in the ExtendedMetadata and performs
the following steps for creation of the context:
Locate entityId of the local SP by parsing part of the URL after /alias/ (e.g. myAlias in https://www.myserver.com/saml_extension/saml/sso/alias/myAlias?idp=myIdp) and matching it with property alias specified in the ExtendedMetadata. In case the URL doesn't contain any alias part the default service provider configured with property hostedSPName on the metadata bean is used.
Populate credential used to decrypt data sent to this service provider. In case ExtendedMetadata specifies property encryptionKey it will be used as an alias to lookup a private key from the keyManager bean. Otherwise defaultKey of the keyManager bean will be used.
Populate credential used for SSL/TLS client authentication. In case ExtendedMetadata specifies property tlsKey it will be used as an alias to lookup key from keyManager bean. Otherwise no credential will be provided for client authentication.
Populate trust engine for verification of signatures. Depending on securityProfile setting in the ExtendedMetadata trust engine based on either Section 8.2.1, “Metadata interoperability profile (MetaIOP)” or Section 8.2.2, “PKIX profile” is created.
Populate trust engine for verification of SSL/TLS connections. Depending on sslSecurityProfile setting in the ExtendedMetadata trust engine based on either Section 8.2.1, “Metadata interoperability profile (MetaIOP)” or Section 8.2.2, “PKIX profile” is created.
During initialization of SSO ContextProvider is also requested to provide metadata of the peer IDP. System performs these steps to locate peer IDP to use:
During initialization of SSO ContextProvider is also requested to provide metadata of the peer IDP. System performs these steps to locate peer IDP to use:
Load parameter idp of the HttpRequest object and try to locate peer IDP by the entityId. When there's no idp parameter provided system will either start IDP discovery process (when enabled in the ExtendedMetadata of the local SP) or use the default IDP specified in the metadata bean.
Reference : Refer the section 10.2 Context Provider of Spring SAML Doc.
Spring SAML Doc
Implementation Doc

Related

How to implement multiple authentication methods in Spring WebFlux Security?

I'd like to provide two ways to authenticate in my application, one is basic auth (users), and the other is some kind of token based (technical users). I understand that I need a custom ReactiveAuthenticationManager but I can't find clues on the big picture. (Actually, there are a very few insights for MVC, and none for WebFlux.)
1) How do I populate the Authentication's name and credentials in the token based approach? If I configure Spring Security to use httpBasic it's already populated. Some kind of filter needed?
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
Since i am decent at Webflux and i have worked a lot with oauth2 i'll try and answer some of your questions.
1) How do I populate the Authentication's name and credentials in the
token based approach? If I configure Spring Security to use httpBasic
it's already populated. Some kind of filter needed?
A token never contains credentials. A token is something you get issued after an authentication has been done. So usually you authenticate against an issuing service. After you have authenticated yourself against that service you will be issued a token.
If its an oauth2 token the token itself is just a random string. It contains no data about the user itself. When this token is sent (using the appropriate header) to a service using spring security. Spring security has a token filter that will basically check that the token is valid, usually by sending the token to the issuer and asking "is this token valid?".
If using a jwt, its different, the jwt must contain some information like issuer, scopes, subject etc. etc. but its basically the same thing, there is a built in filter that will validate the jwt by sending it to the issuer (or using a jwk that the service fetches from the issuer so it can verify the integrity of the jwt without doing an extra request).
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
You don't You usually define multiple SecurityWebFilterChains for different url paths. I have not done this in Webflux Spring Security, but thats how you do it in regular Spring Applications, and i don't see any difference here. Unless you are doing something crazy custom.
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
The answer here is probably no. You see Spring security 4 had very bad support for oauth2 and especially JWT. So people got accustomed to writing their own JWT parsers. When spring Security 5 came, Spring implemented a jwt filter that you can configure and use built in. But there are a lot of outdated Spring Security tutorials out there and foremost there are a lot of developers that don't read the official documentation.
They mostly google tutorials and get the wrong information and then work on that.
But easy explained:
SecurityContextRepository
If you have session based authentication (server establishes a session with a client) it will store the SecurityContext (session) in ThreadLocal during a request. But as soon as the request ends, the session will go lost unless we store it somewhere. The SecurityContextPersistenceFilter will use the SecurityContextRepository to extract the session from ThreadLocal and store it, most common is to store it in the HttpSession.
AuthenticationManager
Override this if you want to do a custom authentication process. Example if you want to validate something, call a custom LDAP, database, etc etc. It\s here you perform you authentication. But remember, most standard logins (like ldap, sql-servers, basic login etc.) already have prebuilt configurable managers implemented, when you select what login type like .httpBasic() you will get a pre-implemented AuthenticationManager.
UserDetailsManager
You override this when you want create a custom UserDetails object (also usually called Principal) In the UserDetailsManager you do you database lookup and fetch the user and then build and return a UserDetails object.
Those two interfaces are the most regular custom implementations, and are used if you need to to basic authentication/session based authentication.
If you wish to do token, you have to think about, who is the token issuer? usually the issuer is separate and all services just get tokens and validate them against the issuer.
I hope this explains some of the questions. I have written this on the bus so some things are probably wrong and not 100% correct etc. etc.

Disable security verify SSL in oracle apex

I'm using Oracle Application Express 11g.
To secure RESTful services I want to create Third Party Authentication for it.
According to this article : http://www.oracle.com/technetwork/developer-tools/rest-data-services/documentation/listener-dev-guide-1979546.html
In order to register my third party user I need to access this url : https://server:port/ords/resteasy/ui/oauth2/clients/ as I don't have SSL every time I face this error(entring the url in http) :
403-Forbidden
This resource must be accessed over HTTPS only
The Question is : how can I disable "security verify SSL" in apex, in order that I never face this error again.
Note that there is no error like this in other pages because I'm not forced to use https, and I'm receiving this error entring the url in http.
https://docs.oracle.com/cd/E37099_01/doc.20/e25066/install.htm#AELIG7183
1.4.5 Using OAuth2 in Non HTTPS Environments
RESTful Services can be protected with the OAuth2 protocol to control access to nonpublic data. To prevent data snooping, OAuth2 requires all requests involved in the OAuth2 authentication process to be transported using HTTPS. The default behavior of Oracle REST Data Services is to verify that all OAuth2 related requests have been received using HTTPS. It will refuse to service any such requests received over HTTP, returning an HTTP status code of 403 Forbidden.
This default behavior can be disabled in environments where HTTPS is not available as follows:
Locate the folder where the Oracle REST Data Services configuration is stored.
Edit the file named defaults.xml.
Add the following setting to the end of this file just before the </properties> tag.
<entry key="security.verifySSL">false</entry>
Save the file.
Restart Oracle REST Data Services if it is running.
Note that it is only appropriate to use this setting in development or test environments. It is never appropriate to use this setting in production environments because it will result in user credentials being passed in clear text.

Multiple User Types - Spring Security Configuration

We have several user types
Internal Users (authenticated using Active Directory)
External Users/Clients (stored in the DB1)
External Users/Vendors (stored in the DB2)
We plan to use Spring Security OAuth2 to generate GWT token that can then be used to call set of webservices
I can use multiple AuthenticationProviders (LDAPAuthenticationProvider and two DAOAuthenticationProviders) but then we will loose ability to have user to be BOTH client and vendor for example (if they use SAME email for authentication). Since it will stop polling providers once authentication is successful.
I can also use profiles #Profile="vendor/client" and start auth server specifically for Client or Vendor authentication - but that means two different processes = more maintenance.
Any other ideas ? Anybody ran into something similar?
There are a couple of options I can think of:
1 - If each different type of user uses a different client ID, then set something in the client details when you load them to show how the user should be authenticated for the client. There's a getAdditionalInformation() method on ClientDetails that returns a Map you can use to store this info
/**
* Additional information for this client, not needed by the vanilla OAuth protocol but might be useful, for example,
* for storing descriptive information.
*
* #return a map of additional information
*/
Map<String, Object> getAdditionalInformation();
2 - Pass in a header or request param that the AuthenticationProvider can then use to determine how to authenticate that user. You'll need to configure your own implementation of WebAuthenticationDetails to retrieve this information from the request.
This should then be available by calling getDetails() on the Authentication object passed into the AuthenticationProvider's authenticate() method.

How to identify provider for oauth2 redirect_uri callback?

Im trying to undertand how to properly identify which provider a returning authorization request was initiated by. I see three approaches:
Use provider specific redirect_uri callback URIs. /oauth2/<provider-name>/callback etc.
Encode provider id/name in state parameter somehow
Store a pending provider id/name in the web session
Try to verify response with all used providers
I've read parts of the OAuth2 spec but I can't find anything discussing it. Looking at other client implementations it seems as provider specific URIs is the most common solution. Am I missing something?
Clients may not be multi-tenant and are tightly integrated with a single Authorization Server, so there's no need to store a provider identifier because there's only a single fixed one. That may be the reason why there's no obvious solution.
Multi-provider clients like your's should store the provider identifier as part of the state. This is because the state should be protected, and the provider specific redirect_uri is not. One could play an access token for provider A against the callback for provider B and thus defeat the purpose of a provider specific callback.
state can be protected either by reference to server state or to an encrypted cookie, or by value in the form of a self-contained encrypted structured value for the state parameter, and thus can be a safe mechanism to store the provide identifier.

SAML Request - Declare Multiple Protocol Bindings

I have implemented a SAML Service Provider to support Single Sign On for an ASP.Net web portal, which is a shrink-wrap software configured on clients' sites and must be able to interact with any SAML-compliant Identity Provider.
My Assertion Consumer Service (ACS) page will accept the SAML Response through both GET and POST methods.
As I understand the SAML protocol, the SAML Request ProtocolBinding property specifies which protocols are supported for the response. Currently, my request specifies the HTTP-Redirect binding. However, I would like to declare that I support both HTTP-Redirect (GET) and HTTP-POST (POST). After searching through more SAML documentation than I care to reiterate, I am unable to find the syntax for declaring multiple supported protocol bindings (or whether it is even valid to do so).
While I could make this declaration configurable, my preference would be to declare both bindings so that the Identity Provider will work without additional configuration of my portal.
Below is a sample of my Authentication Request. Please, if anyone knows a way to declare both HTTP-Redirect AND HTTP-POST for the ProtocolBinding, I would greatly appreciate your input!
<?xml version="1.0" encoding="utf-8"?>
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="[AUTHN_ID]"
Version="2.0"
IssueInstant="[ISSUE_INSTANT]"
ProtocolBinding="urn:oasis:names.tc:SAML:2.0:bindings:HTTP-Redirect"
ProviderName="[PROVIDER_NAME]"
AssertionConsumerServiceURL="[ACS_URL]">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
PortalEntityID
</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
</samlp:AuthnRequest>
Thanks in advance to anyone who can help!
The ProtocolBinding attribute on AuthnRequest is used to specify the expected binding to be used by the IdP when sending their SAML Response XML. HTTP-Redirect isn't a valid option to use here, because of the possible length restriction on the URL querystring; a SAML Response, especially if it's signed, can be pretty lengthy. I'll quote from the SAML spec [SAMLProf]:
...the identity provider issues a <Response> message to be delivered by the user agent to the service provider. Either the HTTP POST or HTTP Artifact binding can be used to transfer the message to the service provider through the user agent. The message may indicate an error or will include (at least) an authentication assertion. The HTTP Redirect binding MUST NOT be used, as the response will typically exceed the URL length permitted by most user agents.
After considerable research, it seems that you can only declare one Protocol Binding in a single SAML request.

Resources