How to validate new SAML certificate - ruby-on-rails

I'm working on an app that acts as a SAML service provider. It's written in Rails and uses the omniauth-saml and ruby-saml gems.
Our certificate is about to expire, and we need to create a new one. I'm tasked with verifying that the new one is working. However, none of the IdPs that I've tested with seem to care which certificate I use. When I set them up with the old cert and then switch our app to using the new one they all allow SP-initiated login as if nothing changed.
The app needs to work with all IdPs, and I think that some of them do validate assertion signatures. I need to find an IdP that fails to accept an SP-initiated login assertion when the signature does not match the one that was set up. I've tried Okta, Jumpcloud, and Ping without any luck.
One question is: why don't these IdPs care about the signature for SP-initiated login. But the main question is: how do I find one that does care so that I can test the new cert?
Thanks!

There are two places where your SP's certificate is used: (1) the SP can digitally sign its authentication request to the IdP, and (2) the IdP can encrypt parts of its response with your SP's public key.
For situation (1), if your SP is signing its requests with the new certificate but the IdP responds as before, it could very well be that the IdP is simply ignoring the signature. The IdP might have to be configured to expect and require signed requests before it will fail on an unknown certificate. But note that it is up to the IdP whether it will verify signed requests; for example, according to this post Okta does not verify the signature of signed authentication requests.
For situation (2) use Firefox's SAML tracer or something similar to verify that part of the response from the IdP is encrypted. If not, that would explain why switching to a new certificate that the IdP does not know about continues to work.
It may also be that your SP needs only to know that the person authenticated successfully against the IdP and nothing else, in which case, your SP's certificate is superfluous.
In particular, the Shibboleth IdP can be configured to send back encrypted assertions.

For me, by far the easiest to use and configure IdP or SP test connectors can be found here: https://support.onelogin.com/hc/en-us/articles/202673944-How-to-Use-the-OneLogin-SAML-Test-Connector
There is a list of test connectors that will help you to test different kinds of connections.

Related

Error message "You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure"

I am developing a web-based application that will allow my trusted staff to edit the titles, descriptions, tags, etc. of my YouTube channel. In attempting to "Opt In" to my own application, I was sent to the callback URI with an error message:
You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure. You can let the app developer know that this app doesn't comply with one or more Google validation rules.
Some history - when I first attempted to obtain a code to exchange to an authorization token, it actually worked! However, as I was writing the code to harvest the code and exchange it for the authorization token, I repeated the "Opt In" process multiple times. Before I was ever able to perfect my code to exchange the code for an authorization token, I began getting the error message to the effect that the app is insecure and cannot be signed in to.
More history - after reading a Stack Overflow article describing something similar, I deleted the project, created a new project, generated a new Client ID and Client Secret, and then repeated the test with the same failure.
I am the only Test User of the app. I can't find any notification in my console alerting me to nature of the security issue triggering the failures. I have reviewed the OAuth policies at
OAuth 2.0 Policies
and cannot find anything even remotely wrong.
What is wrong and how can I fix it?
I also had the same issue.
For me, it turned out that my redirect_uri is not valid. The redirect_uri that gives error:
http://localhost:8000api/vi/oauth/google
What are wrong in my case:
I should put a / before api.
vi is different from what I registered on GCP. It should be v1
I would suggest you to print out the redirect_uri when your app is performing code exchange, and verify every single characters carefully.
Additionally, check out the documentation of Redirect URI validation rules on Google to see if your redirect_uri comply with all the rules.
You probably changed the port where the project is running or you did not define the address where the project is running in Google Cloud.
Google Cloud → APIs and Services → Credentials → OAuth 2 Client ID → change Authorized JavaScript origin to the port that your app runs on the local or shared host.
The URL may take time to define, so it may not work right away, so you can also create a new credential.
For me the redirect_uri was correct, but as a result of an error, the access code was requested for a different client ID.

How can I configure Azure Application Gateway to only accept client certificates with a specific subject

I have configured mutual authentication on an Azure Application Gateway. Currently all client certificates issued by the intermediate CA (as configured on SSL profile) are accepted, but I only want a specific certificate to be granted access, ideally based on the subject of the client certificate. Making changes to the CA that issues the client certificate is not feasible in my case.
Options explored:
Use leaf certificate when configuring SSL profile: app gateway seems to ignore the leaf certificate; all client certificates issued by the intermediate CA are accepted.
Configure a rewrite rule action to pass a server variable (e.g. client_certificate_subject) to backend in a custom request header. This would require changing the backend to interpret the request header, which I’m trying to avoid.
Configure a rewrite rule condition to check server variable (e.g. client_certificate_subject) and conditionally take some action. Ideally the action should set the HTTP response code (without forwarding the request to backend) or rewrite to an error page generated by the app gateway (e.g. HTTP 401 unauthorized / 403 forbidden). Can this be done somehow?
WAF rules don’t seem like a viable option as they don’t have access to server variables
Hoping to find a way of configuring this requirement on the app gateway. Thanks.
I understand that you want to be able to allow specific certificates only based on their subject names etc., to be granted access by the Application Gateway.
You can't use a rewrite rule because in order to "get to" a rule in the first place you have to get through the listener and you can't get through the listener if you can't authenticate with mutual authentication.
At this point, the best way to avoid people from accessing App GW would be to not give the Leaf certificate so they cannot access the same.
Also please note that Application Gateway Mutual Authentication is in preview right now and therefore, it is intended for "Evaluation" and testing, and not production currently. Once it is GA, there will be options to have revocation lists and checks.
Hope this helps. Please do let us know if you have further questions. Thank you!

How does keycloak determine which signature algorithm to use?

I'm writing an application that uses keycloak as its user authentication service. I have normal users, who log in to keycloak from the frontend (web browsers), and service users, who log in from the backend (PHP on IIS). However, when I log in from the backend, keycloak uses HS256 as its signature algorithm for the access token, and thus rejects it for further communication because RS256 is set in the realm and client settings. To get around this issue, I would like to "pretend to be the frontend" to get RS256 signed access tokens for my service users.
For security reasons, I cannot give the HS256 key to the application server, as it's symmetrical and too many people can access the server's code.
I am currently debugging the issue using the same user/pw/client id/grant type both on the frontend and the backend, so that cannot be the issue.
So far I have tried these with no luck:
copying the user agent
copying every single HTTP header (Host, Accept, Content-Type, User-Agent, Accept-Encoding, Connection, even Content-Length is the same as the form data is the same)
double checking if the keycloak login is successful or not - it is, it's just that it uses the wrong signature algorithm
So how does keycloak determine which algorithm to sign tokens with? If it's different from version to version, where should I look in keycloak's code for the answer?
EDIT: clarification of the flow of login and reasons why backend handles it.
If a user logs in, this is what happens:
client --[login data]--> keycloak server
keycloak server --[access and refresh token with direct token granting]--> client
client --[access token]--> app server
(app server validates access token)
app server --[data]--> client
But in some occasions the fifth step's data is the list of users that exist in my realm. The problem with this is that keycloak requires one to have the view-users role to list users, which only exists in the master realm, so I cannot use the logged in user's token to retrieve it.
For this case, I created a special service user in the master realm that has the view-users role, and gets the data like this:
client --[asks for list of users]--> app server
app server --[login data of service user]--> keycloak server
keycloak server --[access token with direct granting]-->app server
app server --[access token]--> keycloak server's get user list API endpoint
(app server filters detailed user data to just a list of usernames)
app server --[list of users]--> client
This makes the the list of usernames effectively public, but all other data remains hidden from the clients - and for security/privacy reasons, I want to keep it this way, so I can't just put the service user's login data in a JS variable on the frontend.
In the latter list, step 4 is the one that fails, as step 3 returns a HS256 signed access token. In the former list, step 2 correctly returns an RS256 signed access token.
Thank you for the clarification. If I may, I will answer your question maybe differently than expected. While you focus on the token signature algorithm, I think there are either mistakes within your OAuth2 flows regarding their usage, or you are facing some misunderstanding.
The fact that both the backend and frontend use "Direct Access Granting" which refers to the OAuth2 flow Resources Owner Credentials Grant is either a false claim or is a mistake in your architecture.
As stated by Keycloak's own documentation (but also slightly differently in official OAuth.2 references):
Resource Owner Password Credentials Grant (Direct Access Grants) ... is used by REST clients that want to obtain a token on behalf of a
user. It is one HTTP POST request that contains the credentials of the
user as well as the id of the client and the client’s secret (if it is
a confidential client). The user’s credentials are sent within form
parameters. The HTTP response contains identity, access, and refresh
tokens.
As far as I can see the application(s) and use case(s) you've described do NOT need this flow.
My proposal
Instead what I'd have seen in your case for flow (1) is Authorization Code flow ...
assuming that "Client" refers to normal users in Browser (redirected to Keycloak auth. from your front app)
and assuming you do not actually need the id and access tokens back in your client, unless you have a valid reasonable reason. As the flows allowing that are considered legacy/deprecated and no more recommended. In this case, we would be speaking of Implicit Flow (and Password Grant flow is also discouraged now).
So I think that the presented exchange (first sequence with points 1 to 5 in your post) is invalid at some point.
For the second flow (backend -> list users), I'd propose two modifications:
Allow users to poll the front end application for the list of users and in turn the front-end will ask the backend to return it. The backend having a service account to a client with view-roles will be able to get the required data:
Client (logged) --> Request list.users to FRONTEND app --> Get list.users from BACKEND app
(<--> Keycloak Server)
<----------------------------------------- Return data.
Use Client Credentials Grant (flow) for Backend <> Keycloak exchanges for this use case. The app will have a service account to which you can assign specific scopes+roles. It will not work on-behalf of any user (even though you could retrieve the original requester another way!) but will do its work in a perfectly safe manner and kept simple. You can even define a specific Client for these exchanges that would be bearer-only.
After all if you go that way you don't have to worry about tokens signature or anything like that. This is handled automatically according to the scheme, flow and parties involved. I believe that by incorrectly making use of the flows you end up having to deal with tricky token issues. According to me that is the root cause and it will be more helpful than focusing on the signature problem. What do you think?
Did I miss something or am I completely wrong...?
You tell me.

URLSession | Authentication Challenge Response | NTLM

I am aware of How to Respond to an Authentication Challengelike we have NTLM Authentication as there are 3 options.
Provide authentication credentials.
Attempt to continue without credentials.
Cancel the authentication request.
But just want to know the thoughts here, when we go with the first option Provide authentication credentials we pass the username and password URLCredential is there any possibility of leakage of credentials, is it secure to pass the credentials, what is happening behind the screens? how Apple network API sending the credentials to the server?
Yes, we can set the policies like server domain, failure count etc. but from the security point of view is it safe? from Man in Middle Attack (MIMA) or anything else?
Maybe the way I have posted my question is not clear but I was looking more from the Application credential security point of view with NTLM Authentication and after lots of Google, I have found, how’s NTLM works and it’s pretty interesting to see that client don’t share the password with the server. here are the steps as follow.
The client makes the request to the server.
The server needs to validate the user because there is no identity so server generates 16 bytes random number called as the challenge and sends it to the client.
Client hash this challenge with the user’s password and return it back to the server that is called the response it also includes username as plain text and challenge sent to the client.
The server sends everything to the domain controller and it uses the username to retrieve the hash of the user’s password from security account manager database and hash the challenge.
Domain controller shares the response back to the server if they are identical then authentication is successful otherwise a failure.
So the interesting part is here that Network API doesn’t share the password with the server it means it very secure.
I hope it will help others, For More.
There are multiple types of challenges, and the answer to your question depends on what type of challenge you're talking about. Each challenge has a protection space, which basically tells what type of challenge you're responding to.
To answer your question for the most common protection spaces:
Basic password-based authentication (NSURLAuthenticationMethodHTTPBasic): The credential you pass is sent in cleartext to the server (HTTP) or encrypted by the session key (HTTPS).
Digest authentication (NSURLAuthenticationMethodHTTPDigest): The credential you pass is cryptographically hashed with a nonce provided by the server, and only the resulting hashed token gets sent over the network.
NTLM authentication (NSURLAuthenticationMethodNTLM): The credential you pass is cryptographically hashed with a nonce sent by the server, and only the resulting hashed token gets sent over the network.
Client Certificate authentication (NSURLAuthenticationMethodClientCertificate): The certificate is sent to the server, but not the private key data. The client uses the private key to sign the prior TLS handshake data as a means of letting the server verify that the client really does have the private key associated with that cert.
Server certificate validation (NSURLAuthenticationMethodServerTrust): If you pass a certificate obtained from the server, you MUST validate it first, or else you effectively reduce the level of security to that of HTTP (i.e. any server can send any cert and you'll be saying to trust that cert when talking to the server).
The list above covers the most common protection spaces. Kerberos is its own animal, and I don't know anything at all about how that works. And there's also the "Form" protection space, which is just a placeholder for custom authentication that you can use in various parts of your app's code, but is not actually supported in any meaningful way.
It is worth noting that Basic, Digest, and NTLM authentication provide no protection against man-in-the-middle attacks if the attacker can alter data in transit, because the authentication token provided does not depend on the rest of the request in any way. Thus, these are really suitable only for use over an encrypted channel (HTTPS).

How to have a SAML request/response signed using Spring Security SAML extension

I was able to have my application act as a SP with the IDP SSOCIRCLE using the Spring Security SAML extension. My customer has the following requirements:
1. Have the assertion signed: The assertion sent from the IDP is signed and it is working fine.
2. Have the request/response signed: When using SSO Circle to generate the metadata file. I selected the option AuthnRequestsSigned to true. I uploaded my SP metadata to the SSO Circle IDP. The SP metadata had the following values as true: AuthnRequestsSigned & WantAssertionsSigned. When running the application neither my request nor the response I get are signed.
I am having issues to have the second requirement done. I am new to SAML and to Security in general. What am I missing here?
UPDATE
After taking into consideration Vladimir's comments. I changed my binding to HTTP-Post, so now I am sending the SAML Request with the signature shown.
I was able to send the request signed using my private key(not the one provided by the sample project) by doing the following:
Create a keystore, CSR, and a public key certificate using the keygen tool.
Update the Digital Signature section in my SP metadata file to have the new certificate
Remove the old SP metadata file from IDP SSOCIRCLE and add the new SP metadata file
Change spring configurations to have the JKSKeyManager to use the new keystore I created with the new alias and password.
What I need to do now is to have the IDP(SSOCIRCLE) send the response where
a. The response is signed
b. The assertion is signed
How can that be achieved? what changes do I need to do to handle that, given that
the signing of the response should be different than the signing of the assertion.
Thanks.
HTTP-Redirect binding requires that any ds:Signature element present on the SAML message itself is removed before sending of the message:
Any signature on the SAML protocol message, including the XML
element itself, MUST be removed. Note that if the content of the message
includes another signature, such as a signed SAML assertion, this
embedded signature is not removed. However, the length of such a message
after encoding essentially precludes using this mechanism. Thus
SAML protocol messages that contain signed content SHOULD NOT be
encoded using this mechanism. (saml2-bindings, 578-582, copy pasted from PDF)
At the same time HTTP-Redirect binding requires that a new digital signature is attached to the GET URL as parameter Signature.
This means that with HTTP-Redirect you cannot send message with Signature on message level, instead the signature is added to the URL. Therefore the whole message sent from Spring SAML to IDP is signed (check it from the data sent from the SP).
There is no standard way to force IDP to send the Response message signed on message level in addition to including signature in the assertion. In case you're using SSL/TLS the authenticity and non-repudiation of the message (characteristics of digital signatures) is provided by transport layer.

Resources