Session Management OpenID Connect Why two Iframes? - session

I have been reading the OpenID Connect draft specification describing how to handle a user log off. Everything points to this super weird, two iframe solution. See here:
openid spec for sessions
and a brief description here:
Hans Zandbelt blog regarding this strategy
can someone explain why I need two separate iframes, and not just one to the openid identity provider, and some javascript on my page to delete the cookie and redirect to the sso login?

I was having the same doubts the other day about why we need two iframes to perform session check. From my point of viewing it, the RP iframe was totally useless. As a matter of fact, it's totally possible to perform the session check with just an iframe pointing to the check_session_iframe url.
The thing is that, when you receive the changed message, you will most likely want to attempt a silent token renewal, as the spec says, and you will need an iframe for doing so, hence the RP iframe.
The spec (4.1 RP Iframe) says:
Upon receipt of changed, the RP MUST perform re-authentication with
prompt=none to obtain the current session state at the OP.
When the RP detects a session state change, it SHOULD first try a prompt=none
request within an iframe to obtain a new ID Token and session state, sending
the old ID Token as the id_token_hint.
I believe the RP iframe is responsible for performing the silent token renewal, upon the receive of a changed message. The RP iframe should then generate a new token request with prompt=none, hence the silently part.
If the RP iframe fails to silently renew the token, then the user is no longer authenticated, and your application should be notified to perform proper actions.

The trigger for the deletion of your local session lives in a different domain i.e. the OpenID Connect Provider's domain. So to learn about the changes happening there you need to "poll" the Provider which involves so-called "cross-domain" communication. To avoid polling a remote URL constantly with a large network traffic overhead, the idea is that you poll for a state change locally by checking the Provider's cookie. That is done by leveraging the postMessage communication framework between iframes because only code presented by the OP can check the OP's cookie.

Related

Does custom security HTTP headers violate separation of concerns

Does custom application specific, security related HTTP headers violate separation of concerns, is it considered a bad practice? I realize using custom header to control the service would tightly couple the client with the service implementation. Or in this case, to control the security framework behavior. The context where I planned using the custom header is the following:
We are using token based authentication, where token has a fixed lifetime, and new token is issued each time authenticated client calls the web API. SPA client may call the server with AJAX in two contexts
User action (navigation and submit)
Automatic refresh (current view re-fetches data at fixed intervals)
Now, if user leaves the page open, the session never expires, as new token is generated for each automatic fetch. Somehow, we need to differentiate user action from automatic refresh in the server side, and issue new token only for user actions.
I realize Websocket based refresh would be one solution, but we have decided to stick with timed AJAX call due specific matters. Another solution would be to provide token refresh as a separate endpoint, but this would violate the DRY principle from client's perspective, and would be more cumbersome to setup with Spring Security.
Only remaining option is to embed the user/automated information in the request itself, and using a header seems a viable option here. A presence of certain header would prevent the token refresh. Easy to implement with a few lines of code.
I'm only concerned, if this couples the client too much with the service implementation. Technically, it doesn't couple client with the service, but the preceding security filter, thus leaking security concerns in the user interface. Ideally security stuff should be transparent to user interface, so new client could be coded without knowing anything about security (especially when cookies are used).
In the other hand, this solution isn't destructive or mutative. It's an optional feature. By client utilizing it, security is enhanced, but in either case never reduced (from the perspective of server, as it is). Now the question is, what principles using a optional header to enhance security is violating, and is it a valid solution in this context?
In my option the security should be maximized transparently, but I don't see how to not leak security concerns in the client in this situation.
It sounds like you're using your own home-built custom Token Authentication solution here. This is not a good idea.
I'll take a moment to explain WHY you don't want to do what you're proposing, and then what the better option is.
First off -- the problem that you're trying to solve here is that you don't want a user to remain logged into your site forever if they leave a tab open. The reason you need to fix this is because right now, you're assigning a new Access Token on EVERY REQUEST from the user.
The correct solution to handling the above problem is to have two types of token.
An Access Token that has a very short lifetime (let's say: 1 hour), and a Refresh Token that has a longer lifetime (let's say: 24 hours).
The way this should work is that:
When the user first authenticates to your service, the Access and Refresh tokens are generated with their respective timeouts.
These tokens are both set in HTTP cookies that the client-side JS cannot access.
From this point on, every time your user's browser makes a request to your service, you'll parse out the Access token from the cookie, check to see if it's valid, then allow the request.
If the Access token is no longer valid (if it has expired), you'll then parse out the Refresh token from the cookie, and see if that is valid.
If the Refresh token is valid, you'll generate a NEW Access token with another 1 hour lifetime, and override the old Access token cookie with the new on.
If the Refresh token is invalid, you'll simply return a 301 redirect to the login page of your app, forcing the user to manually re-authenticate again.
This flow has a number of benefits:
There is a maximum session length, which is technical (duration of Refresh token + duration of Access token) -- aka: 25 hours in this example.
Access tokens are short lived, which means that if a token is somehow compromised, attackers can't use it for very long to impersonate the user.
What's nice about the above flow is that it is a web authorization standard: OAuth2.
The OAuth2 Password Grant flow does EXACTLY what you're describing. It generates both types of tokens, handles 'refreshing' tokens, handles the entire thing from start to finish in a safe, standards-compliant way.
What I'd highly recommend you do is implement an OAuth2 library on both your server and client, which will take care of these needs for you.
Now -- regarding the tokens, most OAuth2 implementations now-a-days will generate tokens as JSON Web Tokens. These are cryptographically signed tokens that provide a number of security benefits.
Anyhow: I hope this was helpful! I author several popular authentication libraries in Python, Node, and Go -- so this comes from my direct experience working with these protocols over the last several years.

Prevent session from being replicated when JSESSIONID cookie copied

Background: I have a javaee webapp deployed on tomcat which uses form based authentication. When the web server receives a login request, it sends the request to a dedicated authentication service which validates user login (User id and password). After successful authentication user's session is maintained in the web server.
Problem: I have written a simple webpp source code here, to simulate the scenario. On successful login the current HttpSession instance is invalidated and new instance is created. For each request for a post login page, the session is validated. A new JSESSIONID cookie is set which is used to identify the user during the session until session is expired or user logs out. This cookie can easily viewed in browser's dev tools. If I copy the cookie and set this in a different browser via JavaScript (document.cookie="JSESSIONID=xyzz") and then try to access a post login page, the server identifies it as a valid request and session is validated successfully. The post login page is served without user being challenged for user Id and password.
POC: User opens chrome and enter the URL http://localhost:8080/mywebapp/ and logs in with admin and pass1234. On successful log in the home page http://localhost:8080/mywebapp/home is shown. Now the JSESSIONID cookie is copied and set in FireFox. User enters http://localhost:8080/mywebapp/home in Firefox and is shown the home page without being challenged for userId and password.
Question: How can this be prevented wherein same session is getting replicated over multiple browsers?
You can't prevent this specific case of simply copying the cookie from your own browser (or by copying the cookie value from a HTTP payload copypaste/screenshot posted by an ignorant somewhere on the Internet). You can at most prevent the cookie getting hijacked by XSS or man-in-middle attacks.
This all is elaborated in Wikipedia page on the subject Session Hijacking of which I snipped away irrelevant parts (either already enforced by Servlet API, or are simply not applicable here).
Prevention
Methods to prevent session hijacking include:
Encryption of the data traffic passed between the parties by using SSL/TLS; in particular the session key (though ideally all traffic for the entire session[11]). This technique is widely relied-upon by web-based banks and other e-commerce services, because it completely prevents sniffing-style attacks. However, it could still be possible to perform some other kind of session hijack. In response, scientists from the Radboud University Nijmegen proposed in 2013 a way to prevent session hijacking by correlating the application session with the SSL/TLS credentials[12]
(snip, not relevant)
(snip, not relevant)
Some services make secondary checks against the identity of the user. For example, a web server could check with each request made that the IP address of the user matched the one last used during that session. This does not prevent attacks by somebody who shares the same IP address, however, and could be frustrating for users whose IP address is liable to change during a browsing session.
Alternatively, some services will change the value of the cookie with each and every request. This dramatically reduces the window in which an attacker can operate and makes it easy to identify whether an attack has taken place, but can cause other technical problems (for example, two legitimate, closely timed requests from the same client can lead to a token check error on the server).
(snip, not relevant)
In other words:
Use HTTPS instead of HTTP to prevent man-in-middle attacks.
Add a checkbox "Lock my IP" to login form and reject requests from different IP associated with same session in a servlet filter. This only works on users who know themselves they have a fixed IP.
Change session cookie on every request. Interesting at first sight, but breaks when user has same website open in multiple browser tabs/windows in same "session".
Not mentioned, but make sure you don't have a XSS hole anywhere, else it's very easy stealing cookies.
Last but not least, I'd like to make clear that this problem is absolutely not specifically related to Servlet API and the JSESSIONID cookie. All other stateful server side languages/frameworks such as PHP (PHPSESSID) and ASP (ASPSESSIONID) also expose exactly the same security problem. The JSESSIONID was previously (decade ago orso) only a bit more in news because by default it was possible to pass the session identifier along in the URL (which was done to support HTTP session in clients who have cookies disabled). Trouble started when ignorant endusers copypasted the full URL with JSESSIONID inside to share links with others. Since Servlet 3.0 you can turn off JSESSIONID in URLs by enforcing a cookie-only policy.
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
How to prevent adding jsessionid at the end of redirected url
remove jsessionid in url rewrite in spring mvc
What you have stated is called session hijacking. There are many good answers on how to prevent it.
Using same Jsession ID to login into other machine
we can use Encryption or hide JSESSIONID using Browser control.
Thanks

Protect Web API from unauthorized applications

I am working on a web page that uses a lot of AJAX to communicate with the server. The server, in turn, has an extensive REST/JSON API exposing the different operations called by the web client.
This web site is used by both anonymous and authenticated users. As you might expect, the web service calls issued by authenticated users require authentication, and are thus protected from unauthorized users or applications.
However, the web site has a lot of features that require no authentication, and some of these make use of anonymous web services. The only way I am using to prevent outsiders from calling this web services is by using a CSRF token. I know, the CSRF token is not very useful in this regard... with some time in hand, you can figure out how to consume the web services even if they use a CSRF token.
Of course, you can use a CAPTCHA to prevent applications or bots from autonomously using your web service. However, any human will be able to use it.
Sharing a secret key between client and server, on the other side, would be useless. This, because of the ability of any outsider to read it from the web page source code.
I would like to make these web services as difficult to invoke as posible to any 3rd party application. What would you do besides using the CSRF token? It sounds a little stupid, but hey, maybe it is stupid and I am just losing my time.
Note: given this application uses a browser and not an "executable" as the client, this question is irrelevant to the discussion. I cannot use a secret between server and client (not to my knowledge, at least)
I would take a few steps.
Force https on the site. Automatically redirect any incoming http requests to https ones (the RequireHttps attribute is handy for this)
Each page needs to (securely, hence the https) send a one-time use token to the client, to be used for the page. The script running on the client can hold this in the page memory. Any request coming back sends a hashed & salted response, along with the nonce salt. The server can repeat the steps with the saved token + salt and hash to confirm the request. (much like explunit's answer above)
(It's worth noting that the secure request from a client isn't being authenticated from a user account, merely a token sent with the full page.)
The definition for one-time could either be session or page load, depending on your security vs convenience preference. Tokens should be long and expired fairly quickly to frustrate attackers.
The SSL + Hash(token + nonce) should be enough for your needs.
This is interesting. Below is a crazy suggestion. Remember, your question is also equally crazy.
Your website, once opened through a browser, should generate a long polling connection (Comet programing). This will create a unique session between the browser and the server. When ur JS is making the ajax call, send some token (unique token every time) to the server through the long polling thread. Let the AJAX also send the same token. At the server, get the AJAX token and check whether you have a similar token in you long polling session. If yes, fulfill the request. Any coder can break this. But, it won't be easy. Chances are the freeboarders won't even see these second piece of comet code. You can implement the comet code in such a way it is not easy to detect or understand. When they call ur service, send a 'Service Unavailable' message. They will be confused. Also make the comet code https.
You can also check how long that long polling thread is open. If the session was just opened and you get a ajax call right away, you can assume it is a 3rd party call. It depends on ur website flow. If ur Ajax call happens after 1 second of page load, you can check for that pattern on server side.
Anyone coding for your public api, will have 1 to 2 secret checks that they wouldn't even know and even if they know, they might be discouraged by all the extra coding they have to do.
You might have an easier problem than the one described in the linked question since you don't need to distribute a binary to the users. Even if your app is open source, the HMAC/signature key (in the "Request Signatures" part of that answer) can be controlled by an environment/configuration setting.
To summarize:
The secret key is not actually sent between client and server. Rather, it's used to sign the requests
Be sure that the requests include some unique/random element (your CSRF key probably suffices) so that two requests for the same API data are not identical.
Sign the request with the secret key and append the signature to the request. You linked to a PHP question but not clear if what language you're using. In .Net I would use a HMAC class such as HMACSHA256.
On the API server-side use the same HMAC object to verify that the request was signed with the same secret key.
Maybe you could use counters to keep track of conversations. Only the Server and Clients will be able to predict the next iteration in a conversation. This way, I think, you can prevent third party applications to impersonate someone (Just an idea though).
At the beginning, they start talking at some iteration (i=0, for example).
Every time the client requests something, the counter is incremented by some number in both the server side and the client (i=i+some_number).
And, after a few minutes of no communication, they both know they have to reset the counter (i=0).
This is just an idea based on the concept of RSA and also placing Fraud Detection on your system. The Risk from Authorized users is minimal however they can attempt to make anonymous calls to your web-service too.
For UN-Authorised users : For each web-service call , generate a token say using RSA which changes after some time(can be configured say 30 min). This way prediction of code is minimized. I have not heard of RSA collision till now. Send this token back to the user for his browser session. For further security , we might want to attach a session id with RSA token. Since session ids are unique new anonymous calls would require new session id.
Calls can be tracked using Auditing mechanism. Also per-web service there can be a different RSA setup. How the Algorithm for Fraud Detection would work is a challenge by itself.
For Authorized Users :
Every user should be tracked by his IP Address using Header block. The RSA token principle can be applied.
The solution is very vague but worth considering.

What's the best way to use HTTP Authentication in an Ajax Application that's not 100% AJAX

I have a standard HTML login page, which I would much rather use than the standard HTTP authentication pop-up provided by browsers. Today, I am using session cookies to keep track of the session after logging in, but I'd like to be stateless and pass the HTTP authentication every time. The web services I am hitting already support this, so this is a browser-only issue.
Adding authentication credentials is trivial in jQuery, but I don't know how to keep them around. If you go from the login page (a jsp) to the Home page (another jsp) you clearly don't keep the username and password fields from the login page. I know some browsers will store your HTTP authentication credentials if you enter them from the pop-up, but I don't know if they get stored when using an XHRRequest. If they do, is there much consistency among browsers?
Also, the user needs to be able to "sign out" of the application, too. If the browser stores the authentication credentials, is there a way to clear them using JavaScript.
I feel like I can't be the first person to try to solve this. Is there some jQuery plugin or something that already handles this? Or is it simply not possible to do what I'm trying to do?
You have 2 options:
1) Client-side storage of credentials -- not a good idea. For obvious reasons you don't want to store the username/password on the client. If you had a hashed version of the password, it might not be so bad, but still not recommended. In any case, if you're going to store on the client side, you either have to use a cookie, or HTML5 local storage (which is not widely supported, yet)
2) Server-side storage of credentials -- typically done with sessions. Then the resultant Session ID can be passed back to the client and persisted in either a cookie or in the URL of each subsequent AJAX call (?SESSID=xyz for example)
The server-side approach would be the most secure, reliable, and easiest to implement
Okay, I'll take a stab at helping ...
Firstly, understand how HTTP authentication works. There are two versions - Basic and Digest. Basic transmits in plaintext, digest is encrypted. With these types of authentication, the username/password are passed in the HTTP header with every single request. The browser captures these at login and they are stored in an inaccessible browser session cookie which is deleted when the browser session is closed. So, in answer to one of your questions, you can't access these from javascript.
You could create your own session cookie variables for username and password. The jQuery functions for this are really simple. See jquery-cookie module as one example of how to set session cookies. These could be retrieved from the session cookie and sent with each ajax request and validated in the server. However, this is not a particulary good way to do authentication since sniffing the network will allow anybody to easily grab your auth details. But, it would work.
Using session cookie based authentication where the session ID is sent sent with each request is the best way to do this. At the server side, you need to have a function called for every HTTP request. This function should do the following:
check to see if the session has been authenticated
if no:
redirect to login screen
if yes:
do authorization and allow the user access to the page
Most web frameworks support session cookie authentication and the management of session ids at the server. This is definately the way to go.
This is interesting one.
Manage user sessions on server by use of cookies. Create a session when user first accesses the login page and pass the session id/key as value to one of the cookie via response. When the user is authenticated put user "key" info in cookie and "values" in application context at server. Once user is logged, any subsequent request will be authenticated based on session cookie value at server. Authorization will be done based on user "key" passed as cookie value.
On logout clear the session based cookies from server and refresh the site to default page.
Cookies are bizarre with different browsers - just a note ;)
Hope this helps.
Update
The answer below was posted in 2012 and the links are mostly dead. However, since then, a more elegant standards-based approach to the same solution appeared using JSON Web Tokens. Here is a good blog post explaining how to use them.
Most answers miss the point, which is to avoid having any server-side session. I don't want any application state in the server. I'll award the bounty to answer that came closest, but the real credit goes to the rest-discuss group and Jon Moore for the correct answer and to Mike Amundsen for helping me to actually understand it.
The best answer I've gotten is to use a cookie, but not the typical automatic session id cookie given to you by most application servers. The cookie (which will automatically be sent with each subsequent request) is a user identifier and time signed by the server. You can include an expiration time with the cookie so it simulates the typical 30 minute session on a server (which means you have to push it forward with subsequent requests) as well as keeps the same cookie from being valid forever.
The XHR/AJAX part is a red herring. This will work whether you are doing XHR requests or an old-fashioned page-by-page web application. The main points are:
The cookie is automatically sent on subsequent requests so there's no
special scripting required - it's just how browsers work already.
The server does not need to store any session for the user, so the user
can hit any server in a cluster and not have to re-authenticate.
Slightly interesting in that you consider pushing some of the authent to the client. If you want a conventional solution, KOGI's server-side suggestion is the way to go.
But you also seem to be asking questions about memory leaks involving your user supplied secrets. Good questions. But to take a general stab at answering that I'd say it would have to be browser specific. It's browser internals, javascript engine internals -dependent where a client side application (i.e., the browser, or js in the browser) is storing the values the user inputs.
Most likely those values are not replicated needlessly throughout memory, but there's no way to guarantee that. Apart from responsible javascript coding practices, there's nothing you can do to guarantee the limit of locations of user inputs.
Slight digression
The basic point is if you store it on the client it is not really secure -- unless, the serve stores encrypted information on the client with a key that only the server (or the user via their correct credentials), has. So you could conceivably code a JS application to do some authent on the client -- much the same as how bank card (used to?) do POS authent by checking the PIN to the PIN on the card, and not back at the DB. It's based on the (somewhat flimsy) assumption the user has no direct read/write access of the "dark area" cookie/local storage on client / mag strip on bank card. So I would only advise this as disqualifier for false authents and not as a sole qualifier for the credentials.
Main point
If you do want to be stateless, just store user credentials in localstorage, or as a cookie but encrypt them with a server key. When you need them send an XHR with the encrypted / use stored credentials to the server over HTTPS, let your server decrypt them and send them to the callback. Then pass those cleartext of HTTPS to do your authent.

Can you help me understand this? "Common REST Mistakes: Sessions are irrelevant"

Disclaimer: I'm new to the REST school of thought, and I'm trying to wrap my mind around it.
So, I'm reading this page, Common REST Mistakes, and I've found I'm completely baffled by the section on sessions being irrelevant. This is what the page says:
There should be no need for a client
to "login" or "start a connection."
HTTP authentication is done
automatically on every message. Client
applications are consumers of
resources, not services. Therefore
there is nothing to log in to! Let's
say that you are booking a flight on a
REST web service. You don't create a
new "session" connection to the
service. Rather you ask the "itinerary
creator object" to create you a new
itinerary. You can start filling in
the blanks but then get some totally
different component elsewhere on the
web to fill in some other blanks.
There is no session so there is no
problem of migrating session state
between clients. There is also no
issue of "session affinity" in the
server (though there are still load
balancing issues to continue).
Okay, I get that HTTP authentication is done automatically on every message - but how? Is the username/password sent with every request? Doesn't that just increase attack surface area? I feel like I'm missing part of the puzzle.
Would it be bad to have a REST service, say, /session, that accepts a GET request, where you'd pass in a username/password as part of the request, and returns a session token if the authentication was successful, that could be then passed along with subsequent requests? Does that make sense from a REST point of view, or is that missing the point?
To be RESTful, each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP.
Okay, I get that HTTP authentication
is done automatically on every message
- but how?
Yes, the username and password is sent with every request. The common methods to do so are basic access authentication and digest access authentication. And yes, an eavesdropper can capture the user's credentials. One would thus encrypt all data sent and received using Transport Layer Security (TLS).
Would it be bad to have a REST
service, say, /session, that accepts a
GET request, where you'd pass in a
username/password as part of the
request, and returns a session token
if the authentication was successful,
that could be then passed along with
subsequent requests? Does that make
sense from a REST point of view, or is
that missing the point?
This would not be RESTful since it carries state but it is however quite common since it's a convenience for users; a user does not have to login each time.
What you describe in a "session token" is commonly referred to as a login cookie. For instance, if you try to login to your Yahoo! account there's a checkbox that says "keep me logged in for 2 weeks". This is essentially saying (in your words) "keep my session token alive for 2 weeks if I login successfully." Web browsers will send such login cookies (and possibly others) with each HTTP request you ask it to make for you.
It is not uncommon for a REST service to require authentication for every HTTP request. For example, Amazon S3 requires that every request have a signature that is derived from the user credentials, the exact request to perform, and the current time. This signature is easy to calculate on the client side, can be quickly verified by the server, and is of limited use to an attacker who intercepts it (since it is based on the current time).
Many people don't understand REST principales very clearly, using a session token doesn't mean always you're stateful, the reason to send username/password with each request is only for authentication and the same for sending a token (generated by login process) just to decide if the client has permission to request data or not, you only violate REST convetions when you use weither username/password or session tokens to decide what data to show !
instead you have to use them only for athentication (to show data or not to show data)
in your case i say YES this is RESTy, but try avoiding using native php sessions in your REST API and start generating your own hashed tokens that expire in determined periode of time!
No, it doesn't miss the point. Google's ClientLogin works in exactly this way with the notable exception that the client is instructed to go to the "/session" using a HTTP 401 response. But this doesn't create a session, it only creates a way for clients to (temporarily) authenticate themselves without passing the credentials in the clear, and for the server to control the validity of these temporary credentials as it sees fit.
Okay, I get that HTTP authentication
is done automatically on every message
- but how?
"Authorization:" HTTP header send by client. Either basic (plain text) or digest.
Would it be bad to have a REST
service, say, /session, that accepts a
GET request, where you'd pass in a
username/password as part of the
request, and returns a session token
if the authentication was successful,
that could be then passed along with
subsequent requests? Does that make
sense from a REST point of view, or is
that missing the point?
The whole idea of session is to make stateful applications using stateless protocol (HTTP) and dumb client (web browser), by maintaining the state on server's side. One of the REST principles is "Every resource is uniquely addressable using a universal syntax for use in hypermedia links". Session variables are something that cannot be accessed via URI. Truly RESTful application would maintain state on client's side, sending all the necessary variables over by HTTP, preferably in the URI.
Example: search with pagination. You'd have URL in form
http://server/search/urlencoded-search-terms/page_num
It's has a lot in common with bookmarkable URLs
I think your suggestion is OK, if you want to control the client session life time. I think that RESTful architecture encourages you to develop stateless applications. As #2pence wrote "each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP" .
However, not always that is the case, sometimes the application needs to tell when client logs-in or logs-out and to maintain resources such as locks or licenses based on this information. See my follow up question for an example of such case.

Resources