In the IdP metadata we have a POST binding set to https://www.example.com/Auth95 (all the bindings are set to the same url)
We see the AuthNRequest going with a Destination of https://www.example.com/Auth95
The user logs in successfully and the Response comes back successful but it has an Issuer of https://www.example.com/Auth3 and fails signature validation. Is it SAML-legal to have the Destination and Issuer different and if so how do configure spring-security-saml to ignore the path?
Yes, destination and issuer can differ. Destination is URL of the endpoint where SAML messages get delivered, while Issuer corresponds to entityId of the IDP. Simply change entityId in the IDP metadata you import to Spring SAML to "https://www.example.com/Auth3" and you should be good to go (provided validation actually fails on the Issuer, not on signature as you say).
Related
I'm trying to get my web app SAML-integrated with ADFS (it already works with other IdPs). The AuthnRequest that's sent to ADFS is unsigned. ADFS rejects the request, leaving this message in its log:
Microsoft.IdentityModel.Protocols.XmlSignature.SignatureVerificationFailedException: MSIS0037: No signature verification certificate found for issuer 'com.onshape.saml2.sp'.
I've tried doing:
Set-AdfsRelyingPartyTrust -SignedSamlRequestsRequired $False
but that didn't help.
Can I configure ADFS to accept my app's unsigned requests? Or make some change to my app to make it generate requests that ADFS will accept?
The error message is a bit misleading - the usual root cause is a mismatch between the issuer in your authentication request (com.onshape.saml2.sp) and the entity ID of the service provider you registered with ADFS.
I'm trying to create an authentication flow where the user's access token is kept in a server-side session along with the refresh token, and when the token expires it is renewed if the session is still valid. However, the token I get back from Azure AD after refresh has an invalid signature, when verifying it with the same method as the original token.
Here's a runnable gist that illustrates the problem: https://gist.github.com/tlycken/fdaf47dc31e03de43a1a07fbbea2ab91
What I'm doing is basically this:
When the user requests a page, check for a session. If none exists, redirect to /auth which redirects to Azure AD, and when I'm returned I have a valid token which I store in the session.
Verify the token from the session using jwks-rsa. (This normally works fine, so I'm purposely adding something to the token string to make the signature invalid in the test code.)
If token verification failed, and there is a refresh token on the session, try to fetch a new token using that refresh token. This request normally returns with status 200 OK and a new set of access/refresh tokens.
Verify the new access token using the same code as was used to verify the old one (now without garbling the token). This should work, IIUC, but it fails with the error invalid signature.
Why does my newly refreshed token not pass verification?
Update:
I was able to create a simpler flow for reproducing this; the gist has been updated. It now does the following (printing these messages, along the way):
no session, redirecting to /auth
successful auth callback, redirecting to /
verifying old token
decoded user id e7f02a6e-510c-430d-905c-f8a0e63206c2
refreshing
fetching /me with renewed token
got user id e7f02a6e-510c-430d-905c-f8a0e63206c2
verifying new token
token verification failed: invalid signature
In addition to validating the token myself, I now also send a request to Azure with it, hoping that such a request would fail for an invalid token. But it passes!
You're code is using the v1 Endpoint to obtain the initial access token but the v2 Endpoint to exorcise the refresh token. These two endpoints operate differently. In particular, the v1 Endpoint uses "resource" while v2 uses "scopes".
The reason this is happening is your calling v1 explicitly but relying on the v2 /openid-configuration for the Refresh Token endpoint.
To correct this, change line 19 of refresh-auth-token.js to
const configResponse =
await fetch(`https://login.microsoftonline.com/${AZURE_TENANT}/.well-known/openid-configuration`)
I have an application registered in Azure AD which uses certificates. I am trying to write a script which would add a new certificate to the application. This can be used to add a new certificate when the existing certificate is going to expire.
I am trying to use AddKey function of Azure AD Graph API. The request body of this api as a parameter 'proof' which is a JWT assertion signed by the existing certificate of the application. The doc says the "aud" claim in JWT should be set to "AAD Graph SPN". Here what is meant by "AAD Graph SPN"?
I tried with a JWT where "aud" was set to "00000002-0000-0000-c000-000000000000". But I am getting the following error,
{
"odata.error": {
"code":"Authorization_RequestDenied",
"message":{
"lang":"en",
"value":"Insufficient privileges to complete the operation."
}
}
}
Any thoughts on this?
I am getting the access token to call the Azure AD Graph API via "Resource Owner Credentials Grant" flow . To get the access token i am using the client_id "1950a258-227b-4e31-a9cf-717495945fc2" (The Well Known Client ID for Azure PowerShell")
My script (For deployment purpose) does something like below,
i) Get the access token as described above and registers a new application in Azure AD with a initial certificate.
ii) When the initial certificate is about to expire it should add a new certificate to the created application.
According to the documentation, you must use a self-signed JWT token to access that API:
As part of the request validation for this service action, a proof of
possession of an existing key is verified before the action can be
performed. The proof is represented by a self-signed JWT token. The
requesting application needs to generate a self-signed JWT token with
the following requirements...
The "Resource Owner Credentials Grant" won't work here in this situation. Instead, use the "Client Credentials Grant":
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service
The application you want to update should be the Client ID used to get this access token.
The other option is to update the application directly using an PATCH request on the Application Object:
https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/entity-and-complex-type-reference#application-entity
Using this method, you should be able to update using the method you described above (user credentials and an external Client ID)
Let me know if this helps.
I'm working on a OAuth2 server project. Can I use domain name for generating client_id ?
Ex: For instance if Google registering an app in my server, then the client_id will be google.com
Am i allowed to use dots in client_id? Is it wise to use domain as client_id ? what are the drawbacks?
According to Specification
The authorization server issues the registered client a client
identifier -- a unique string representing the registration
information provided by the client. The client identifier is not a
secret; it is exposed to the resource owner and MUST NOT be used
alone for client authentication. The client identifier is unique to
the authorization server.
The client identifier string size is left undefined by this
specification. The client should avoid making assumptions about the
identifier size. The authorization server SHOULD document the size
of any identifier it issues.
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.