I am trying to create a client that uses SAML, but I am not sure what the Master SAML Processing URL field should be.
I read the documentation, but its still not clear to me.
SAML uses assertions in order to verify resource accesses. The service provider needs to declare a specific url for this assertion exchange. On the other hand, there's the url which the Service Provider uses to manage the Single Sign Out process. The Master SAML Processing URL of Keycloak just lets you specify the same endpoint for both processes (you can still configure them individually using the fine grain configuration).
Related
I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.
As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.
That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:
I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.
On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.
On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.
I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.
You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.
Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.
Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.
There's an open standard now called "JSON Web Token",
see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating tokens that assert some number of claims. For example, a
server could generate a token that has the claim "logged in as admin"
and provide that to a client. The client could then use that token to
prove that they are logged in as admin. The tokens are signed by the
server's key, so the server is able to verify that the token is
legitimate. The tokens are designed to be compact, URL-safe and usable
especially in web browser single sign-on (SSO) context. JWT claims can
be typically used to pass identity of authenticated users between an
identity provider and a service provider, or any other type of claims
as required by business processes.[1][2] The tokens can also be
authenticated and encrypted.[3][4]
Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.)
Check this var on the server-side on every API call.
P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.
Excuse me #MarkAmery and Eugene, but that is incorrect.
Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:
First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password.
Before authentication the calls to the API are not accepted.
During authentication a "token" is returned.
After authentication only API calls with the authentication "token" will be accepted.
Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.
Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.
Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.
So you do not have to worry that this may be an unauthorized user without credentials.
(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)
Here's what I do:
Secure the API with an HTTP Header with calls such as X-APITOKEN:
Use session variables in PHP. Have a login system in place and save the user token in session variables.
Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.
i'm still pretty new to web-development I worked myself through Web Development with Node and Express by Ethan Brown and currently i'm trying to get a good understanding for the examples given by Full-Stack React Projects by Shama Hoque.
Currently i'm trying to refactor a lot of things that used to be server-side-rendered to be handled in the React SPA client. One of these things includes a simple GitHub widget, my previous flow worked like this:
The client user authenticates with my server using a GitHub OAuth app.
The server stores the access Token returned to the callback in a database on the server.
The server makes calls to the GitHub API using the user access Token stored in the database.
The server processes the results, renders it in HTML and sends it to the client.
However I realized that there is also possibility to implement it like this.
The client user authenticates with my server using a GitHub OAuth app.
The server passes the access Token returned to the callback back to the client
The client makes calls to the GitHub API using the user access token obtained from the server.
The client processes the results and renders it apropiately.
As far as I understand there is no inherent security risk doing this(a malacious user could interecept the access token when the oAuth provider redirects to the callback either way) and both flows have their up and downsides (e.g. 2nd flow produces less load on the server but also sacrifices control). Since I'm new to this and I came up with the 2nd flow myself I wanna double check if this is something thats ok to be doing or I've missed something, if so, what did I miss? Is there any other major down or upsides i'm not considering?
What you've implemented is the OAuth Authorization Flow. In this flow, the client (aka the browser) never gets the access token. Only your webserver gets it. And thus the client cannot make calls to the resource server (github). Your webserver makes the calls on the client's behalf.
You say:
a malacious user could interecept the access token when the oAuth provider redirects to the callback either way
However, if you implement the flow correctly, this is not true. This is because once you authenticate with the resource server, it only gives the browser an authentication code. This code is just a temporary ticket that can be exchanged for an access token. However, to exchange a code for the access token, you have to know a client secret. Only your web server knows the secret. So your browser sends the code to your server, and your server calls the resource server (github) with the code + secret to get the token.
The second flow you describe is the OAuth Implicit Flow.
This flow is very much what you described: After the user authenticates with the resource server, the browser ends up with the access token and just calls the resource server directly.
Both flows are very common. The Implicit flow is slightly less secure because there is more opportunity for Bad Guys to get access to the token in the browser's memory (or local storage, or cookie storage). The Authorization Flow is a bit more secure because the token stays on your server, and you do not have to depend upon users to keep it secure.
We are trying to implement SSO, using OneLogin as the IdP with our Cisco Call Manager cluster using a single agreement for all the servers in the cluster.
This just basically means that our metadata file contains a separate AssertionConsumerService tag for every server in the cluster.
However we are hitting an issue where in the SAML response the Destination is not recognized as valid.
My question would be, in the case of multiple ACS' used, what would the destination field need to look like in the SAML response? Does the IdP need to recognize which consumer the request came from and dynamically change the destination in the response to be the correct one for the specific consumer?
Right now the SAML response looks something like this:
<samlp:Response
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Destination="https://<CUCM_2>:8443/ssosp/saml/SSO/alias/<CUCM_2>https://<CUCM_2>:8443/ssosp/saml/SSO/alias/<CUCM_2>https://<IMP_1>:8443/ssosp/saml/SSO/alias/<IMP_1>https://<IMP_1>:8443/ssosp/saml/SSO/alias/<IMP_1>https://<CUCM_1>:8443/ssosp/saml/SSO/alias/<CUCM_1>https://<CUCM_1>:8443/ssosp/saml/SSO/alias/<CUCM_1>" ID="pfx117d2cec-f554-1fba-ff86-8db77b497e35" InResponseTo="s2ded98fb1a7423ea7bb1fcc95cf5c57ae3bf19684" IssueInstant="2019-02-18T16:06:06Z" Version="2.0">
and we get the same jumble for Recipient attribute in SubjectConfirmationData
With a proper cluster, you'd have a single ACS URL and the cluster would manage the user session between cluster members outside of SAML. I've not heard of multiple ACS URLs being used for a single SAML supporting SP. The IdP ( Onelogin ) needs to know specifically where to send the SAML response. I think you'll need to look at your cluster configuration and see whether it can be configured as a endpoint regardless of the cluster instance that initiates the SAML request.
Ah, but Cisco is special, don't you know? :)
I managed to get it working in the meantime and whoever is reading this thread in the future, I can confirm that OneLogin can now support Cisco clusters using a single cluster-wide metadata. But for any other IdP the setup is:
IdP requirements
CUCM only supports NameIDFormat as transient
HTTP-POST and HTTP-Redirect SAML bindings need to be enabled
SAML specification that allows for the definition of multiple AssertionConsumerService tags needs to be supported
Operation
When setting up SSO, within the metadata generated by CUCM if using cluster wide SSO mode, multiple AssertionConsumerService tags are defined. Two for each server in the cluster, one using the POST method and one using Redirect. Each ACS also has an Index tag, that starts at 0. This is sent to the IdP
When trying to authenticate a SAML request is sent to the IdP, within the request the AssertionConsumerServiceIndex field is set to the Index of the server from which the request was generated, as defined in the metadata originally provided to the IdP
The IdP then sends back a SAML response, in which the Destination and Recipient tags are set to match the Location tag from the metadata corresponding to the requesting server
As an SP, we've opted for the POST binding option - it seemed to be the advised approach. SAML is now set up and working with the IDP. We would now like to change to Redirect as it is better handled in Ajax calls after timeout.
My question is whether we can switch from POST to Redirect without incurring a setup change on the IDP side. Seeing as both bindings are just using the UserAgent (browser) as a transport anyway, I figured it may be possible. But the binding is defined in the AssertionConsumerService in the metadata which indicates that IDP would need to be informed and have its configuration changed.
Sending a SAML Response (which is what is sent to an Assertion Consumer Service endpoint) via Redirect is not supported by the SAML spec since responses easily get too large to send as a query parameter. See line 420 in the SAML Web SSO Profile spec https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
Identity Provider issues to Service Provider In step 5, the identity provider issues a 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.
You can switch to Artifact, though SP metadata will need to updated on the IDP to relay the changed endpoint.
We are implementing SAML integration and I am the service provider and my identity provider is asking me to send "SAML Consumer URL" and "RelayState"
I would need help to understand what is SAML consumer URL & RelayState and how do I get/generate it for my application.
Thank you for your time and help!
TLDR, AssertionConsumerUrl (ACS) endpoint is SAML protocol endpoint, RelayState is like cross-domain cookie, used to coordinate messages and actions of IdPs and SPs.
In 5.1.Web Browser SSO Profile of SAML 2.0 Technical Review, it will give you a general understanding of how the flow goes.
Down to the SSO implementation, for example Shibboleth, this FlowAndConfig doc details the SSO flow pretty well.
In 2. SP Determines IdP and Issues Authentication Request:
Cookie Set by SP
During this step, the SP will preserve the original
resource requested by the browser using a "relay state" mechanism,
which is configured by a relayState property on the <SessionInitiator>
element. The default mechanism does not rely on a cookie any longer,
but many systems do, and send a state management cookie containing the
resource URL to the client along with the request prepared for the IdP
or DS/WAYF.
In 5. Back to the SP:
The browser delivers the response from the IdP to an Assertion Consumer Service endpoint at the SP.
relay state info returned from IdP to SP
Cookie Read by SP
The "relay state" information returned by the IdP, if any, will have
been created by the SP and if using a cookie, will point to a
specially named cookie that should accompany the authentication
response supplied to the ACS endpoint in this step. This is the cookie
set in Step 2 above. If this cookie is missing (or if no relay state
exists at all), the associated application's homeURL property is
substituted as a fall back.
Also, Shibboleth has some wiki for those two terms as well.
AssertionConsumerService concept
RelayState concept
Hope it helps!