I am new to WIF.
And now I encountered a problem when performing single sign off.
The following is the background of my problem:
First of all, I am working on two old application A and B, which they stores the user's information in their own session variable after authenticating a user. And App A and B have their own local database. Now, my work is to use ADFS to enable SSO (Single Sign On) between two applications.
Now, I create a new active directory to store the users centrally.
When a user try to login application A through ADFS, application A need to check the user name in the claim is exist in the local database. If exists, the user can login to App A. Otherwise, App A will reject the claim.
Here is the technical part:
I extend the WSFederationAuthenticationModule and check the incoming claim with the local database in the method OnSessionSecurityTokenCreated. If the result is matched, I retrieve the user information from local database and store it in the session variable (so that i can minimized the code change). App B uses the same approach.
I am happy with the SSO from here. But the problem come when i perform single sign off:
When I logout from App A, i first clean up the own session in App A and call the WSFederationAuthenticationModule.FederatedSignOut method. However, App B do not clean up its own session. I suppose the OnSignedOut in WSFederationAuthenticationModule will be invoked. How can i clean up the App B's session when App A is signed out?
It may be very confusing. Please leave any comments if you find something unclear or need further explanation.
Signout in WS-Fed is implemented by ADFS (it asks for a gif with app/?wa=wsignoutcleanup1.0), not only locally. That is the only way to notify the other app.
Your app has to to redirect to ADFS with a signouturl. Then both apps will be notified and can cleanup their session state (with the gif request).
Related
I am implementing OAuth2 authentication for one of my GWT projects (let's call it GWT-app). The application responsible for authentication is a third-party application based on Spring Framework-3.1.2.RELEASE and uses its OAuth2 implementation included in Spring Security-3.1.3.RELEASE (let's call it OAuth-app).
GWT-app is a management application for managing user and stores. Each user has one or more manager accounts. A manager account may have one or more stores attached to it so that he can manage them altogether from one screen of the GWT-app.
It means that the user may potentially have to authenticate many times through different manager accounts to display stores by manager account on the app.
So on the StoreManagement.java page of my GWT-app, I have the following :
private final Map<String, ManagerAndStoresProxy> managerAndStores = Maps.newTreeMap(Ordering.natural());
after authentication, this map should be populated with Manager name and a List of attached stores for each.
OAUTH2 FLOW
The Authorization-code flow is used for authentication. When GWT-app wants to authenticate someone, it redirects the user to a login page on OAuth-app. The user enters his credentials and will be presented with an authorization page asking him whether he wants to allow GWT-app to access his information. If the user clicks on authorize, he is redirected back to the GWT-app with an access token.
THE PROBLEM
The only issue is that since GWT-app is redirecting the user to another application for authentication, the first time the authentication works and the map is populated correctly but if I have to authenticate another account then the previously authenticated account is cleared and can not be retrieved because of the redirection.
The question is then : how can I proceed to persist this map and retrieve it back when a second (third, fourth and so on) authentication flow is over (i.e after the url-redirection of OAuth-app).
WHAT I HAVE TRIED SO FAR
What I did so far is that when the user wants to proceed with authentication from the StoreManagement.java page, he is presented with a popup redirected to the OAuth-app authentication page. The access token is then retrieved from this popup but I have to send it back to the parent window (i.e StoreManagement.java page). This can be done via a HTTP GET parameter but this method reloads the parent page and the result is the same: the previously authenticated account is cleared.
QUESTION
What is the best way to handle this situation without clearing the previous context and without requiring any server-side session mechanism whatsoever ?
The root of the problem is using the authorization code grant; the implicit grant (aka client-side flow) would be a much better fit.
If your app is not limited by old browsers in terms of compatibility then you can try to store all necessary things in HTML5 Web Storage.
I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.
I am building an iOS application and the user authenticates with my web service. I don't want them to login every time the app launches (the token lasts a month). So I'd like to cache this on the device somewhere.
What's the best way to do this, securely?
Can I just rely on the app remaining suspended and keeping the token in 'memory'?
2 options
Make use of NSUserdefault(store as access token or textfield inputs[Remember me option])
Keychain access(recommended) for doing the job.
NSUserdefaults is not secure for storing such credible values which is for authentication purpose.Keychain on the other hand is made to do this,safe and secure.
You can't rely that iOS will keep your application forever in the memory. So, you have to save the token to persistent storage at some point.
Look at Keychain Service for iOS. This is the best place to store things like passwords, tokens and other keys.
You can't do it "securely." A token is public knowledge, and as soon as its on your device a hacker could gain access to it no matter what you try to do to protect it. Putting it in the keychain won't change this fact. Even if you store it there, which would make it secure while it's in there, they can simply wait until it expires then snag the next one when it comes in over the wire next time. Your access tokens aren't the thing you need to worry about securing, because you can't, in fact, do that in a mobile environment.
What this means is that you can store it anywhere you'd like. NSUserDefaults is fine, the keychain is fine, a database is fine, a text file in your documents directory is fine. All of them are equally secure because a determined hacker can simply wait for the right opportunity to access the data they want. You should instead worry about securing your users' authentication credentials. Make sure you store those in the keychain, and only ever communicate with your API over HTTPS to a server with a valid SSL certificate.
I'm creating an iphone app where the user logins once (when they open the app for the first time), then will never have to login again (like how instagram does it). The app will automatically log them in the next time they open it up. However, the app makes a bunch of requests to a web server.
What is the best way for the server to issue session tokens? How long should the session tokens be valid for? How can I ensure the user never has to log in again, while still providing secure session tokens.
One approach is for the server to issue a token to the user when the user logs in for the first time, and make that token permanent. That, however, does not seem secure.
Thanks for the help!
Well, generally the session is already handled through session cookies. Unless you're planning to have third parties connect to your service, I think it's a bit overkill to do anything besides basic http authentication. I would definitely send all of your connection requests over an https connection though.
As far as persisting the session on the iPhone side, you can save the user and password in the Keychain, and then automatically retrieve and send it to the server when it requires you to log in again, without having to prompt the user to log in again. How often you want the sessions to last on the server end is really up to you.
What is the best way for the server to issue session tokens?
One way to do it is using OAuth. It is more complex than cookies but it has more features.
A token is granted to each application and can be revoked by the user from a page in the server. This token can be permanent or temporary. You can store it as plain text or inside the iPhone keychain, depending on the level of security you need. There is open free code for server and client implementations. Another benefit is that clients can log in your service using their Twitter/Facebook/... account so they don't need to register on your site.
I'm building an app that performs similar functionality that one website does: register, login, submit order, view orders and etc. Now, do I have to do anything explicitly in order to get things working?
After successful login, a webserver establishes a session and sesssion ID and related session info is written to related cookie. IMHO, I just need to call webservice with login credentials and then the rest will be done implicitly. After successful login, every requested user page from user area will be checked with sent cookies and session file at server side. So, do I have to do anything else in order to get into secure area?
Agree with what #sicKo has said. Remember, sending data over wireless network is not secure. Do be careful on the transactions when money and authentication involved.
In addition to what #sicKo has said, you may now consider the coming iOS5, store the value at iCloud.
You just have to send the value to verify the user to the webserver.. and u can keep the session alive in iPhone using NSuserdefault..
U might want to encrypt the sensitive data send over the network such as username and password.