I'm working on a native Swift iOS app. I've done a lot of reading recently about OAuth 2.0, including this answer, a fair bit of RFC 6749, and several other tutorials. There are lots of comments about how using an embedded webview isn't ideal, because cookies can't be kept secure, hence SFSafariViewController and ASWebAuthenticationSession.
But I haven't seen much talk about a login without a webview/browser at all, collecting user credentials through a UIView form, using a Resource Owner Password Credentials Grant and sending data directly with a URLRequest. I'm building my own application, with my own resource server, and my own authentication server (or using something like Auth0), which is only handling access to my app's protected resources. So everything is 'highly trusted' here. But I've seen notices like the following concerning a resource owner password credentials grant (from here):
The authorization server should take special care when enabling this
grant type and only allow it when other flows are not viable.
Technically, using another flow is 'viable' - I could build it. Does using an external user-agent, SFSafariViewController or ASWebAuthenticationSession still offer security benefits that can't be matched with a native login in this scenario?
One benefit of using an external user-agent that comes to mind is upgrading to 2-factor or multi-factor authentication in general.
Related
I'm working on a native app which will use OAuth to allow the user to sign in (or access material itself) to another website. I know I'll be making use of the implicit flow or authorization code flow for OAuth, however all my research regarding security seems to relate to the client secret.
It seems to be the client id for my app (which is provided by the 3rd party site) will be public and therefore exposed. This would allow someone else to take it and, following the same implicit flow, masquerade as my application. Is this just the nature of oauth?
Is there a way of storing this information so it cannot be stolen?
EDIT:
I'd just like to clarify - I understand oauth keeps the user's information safe from my app and ideally interceptors. But what is stopping someone from taking my client id (as it is publicly visible through the auth process) and using it for themselves? Are any measures that can be taken defeated by open sourcing the app?
The client id can't be protected because it is send as a query parameter in the authorization request.
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
(You could use a web view inside your native app and hide the address bar, but then your app would have access to the user's credentials.)
Further explanations:
Using the implicit flow in native apps is not recommended, because an attacker could register your redirect URI at the OS and could catch the callback with the access token.
The authorization code flow is a better option. If you are able to store the client secret securely within your app (see link below), an attacker could use your client id to start the authorization or catch the callback, but he wouldn't be able to use the authorization code to get an access token.
Links:
Best practices for storing and protecting private API keys
How to avoid reverse engineering of an APK file
Best practices for implementing OAuth in native applications
RFC for PKCE
Before you put me down for asking too basic a question without doing any homework, I'd like to say that I have been doing a lot of reading on these topics, but I'm still confused.
My needs seem simple enough. At my company, we have a bunch of Ruby on Rails applications. I want to build an SSO authentication service which all those applications should use.
Trying to do some research on how to go about doing this, I read about CAS, SAML and OAuth2. (I know that the "Auth" in OAuth stands for authorization, and not authentication, but I read enough articles saying how OAuth can be used for authentication just fine - this is one of them.)
Could someone tell me in simple terms what these 3 are? Are they alternatives (competing)? Is it even right to be comparing them?
And there are so many gems which all seem to be saying very similar stuff:
https://github.com/rubycas/rubycas-server and https://github.com/rubycas/rubycas-client
https://github.com/nbudin/devise_cas_authenticatable
https://github.com/onelogin/ruby-saml
CASino and https://github.com/rbCAS/casino-activerecord_authenticator
And I am sure there are hundreds of OAuth related gems.
I just want a separate Rails application which handles all the authentication for my other Rails apps.
Note: I do not want to allow users to use their Google / Facebook accounts to login. Our users already have accounts on our site. I want them to be able to login using that account once and be able to access all our apps without signing in again. Signing out in any app should sign them out of all apps.
UPDATE
I have come across these two OAuth solutions:
http://dev.mikamai.com/post/110722727899/oauth2-on-rails
http://blog.yorkxin.org/posts/2013/11/05/oauth2-tutorial-grape-api-doorkeeper-en/
They seem to be describing something very similar to what I want. But I haven't found any guide / blog post / tutorial showing how to do this with SAML / CAS.
Suggestions welcome.
UPDATE 2
More details about our use-case.
We do not have any existing SAML architecture in place. Primarily, it is going to be OUR users (registered directly on our website) who are going to be accessing all our applications. In the future, we may have third-party (partner) companies calling our APIs. We may also have users from these third-party (partner) companies (registered on their websites) accessing our apps.
CAS-Server:
A stand-alone central login page where the user enters their credentials (i.e. their username and password).
CAS supports the standardized SAML 1.1 protocol primarily to support
attribute release to clients and single sign-out.
(a table in a SQL database, ActiveDirectory/LDAP, Google accounts, etc.)
Full compatibility with the open, multi-platform CAS protocol (CAS clients are implemented for a wide range of platforms, including PHP, various Java frameworks, .NET, Zope, etc.)
Multi-language localization -- RubyCAS-Server automatically detects the user's preferred language and presents the appropriate interface.
SAML :
Security Assertion Markup Language is an XML-based, open-standard data format for exchanging authentication and authorization data between parties, in particular, between an identity provider and a service provider.
SAML authorization is a two step process and you are expected to implement support for both.
OAuth 2.0:
The OAuth 2.0 authorization framework enables a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf.
Important Note :
SAML has one feature that OAuth2 lacks: the SAML token contains the user identity information (because of signing). With OAuth2, you don't get that out of the box, and instead, the Resource Server needs to make an additional round trip to validate the token with the Authorization Server.
On the other hand, with OAuth2 you can invalidate an access token on the Authorization Server, and disable it from further access to the Resource Server.
Both approaches have nice features and both will work for SSO. We have proved out both concepts in multiple languages and various kinds of applications. At the end of the day OAuth2 seems to be a better fit for our needs (since there isn't an existing SAML infrastructure in place to utilize).
OAuth2 provides a simpler and more standardized solution which covers
all of our current needs and avoids the use of workarounds for
interoperability with native applications.
When should I use which?
1.If your usecase involves SSO (when at least one actor or participant is an enterprise), then use SAML.
2.If your usecase involves providing access (temporarily or permanent) to resources (such as accounts, pictures, files etc), then use OAuth.
3.If you need to provide access to a partner or customer application to your portal, then use SAML.
4.If your usecase requires a centralized identity source, then use SAML (Identity provider).
5.If your usecase involves mobile devices, then OAuth2 with some form of Bearer Tokens is appropriate.
Reference 1,Reference 2,Reference 3
If you need to authenticate for LDAP or ActiveDirectory then a solution like one of the CAS gems you mentioned above is right for you (RubyCAS, CASino).
If you can afford it, one of the commercial vendors (like Okta) is your best option because they will stay on top of security patches and manage your authentication needs for you. In particular, if you have to support ActiveDirectory, they've already implemented it.
OAuth is most useful for third party authentication, though it can do SSO. So if you wanted to support Google / Facebook logins or be a third party authenticator then it's a great choice. Since you don't want to support Google / Facebook then OAuth is probably not what you want.
If you are only intending to use HTTP POST for your SSO needs then the ruby-saml gem could be the way to go. You would have to implement your own Identity provider and add a service provider component to all your websites (possibly in the form of a gem.) Part of what you would need is a rails api to act as your identity provider. This gem helps support writing API's in rails.
EDIT
You mention the possibility that future third party users might be logging on to your site. This changes your calculus away from rolling your own ruby-saml solution.
The best way to share your authentication API is to implement an OAuth layer. Doorkeeper is a popular solution and is fast becoming the standard for Rails authentication. It's community support, flexibility and ease of use make it the best way to go for a consumable authentication API.
Railscast for implementing doorkeeper
Anjan.
I've used CAS and OAuth in my work. Here are some of my opinions, and hope to help.
Basically
Both CAS and SAML aim to solve SSO situation. And CAS is a service or an authentication system, which can support SAML protocol.
OAuth aims to solve authorization and authentication.
And in practice,
Both CAS and SAML act as an gateway in front of a group of applications which belong to one organization. Just like your case.
OAuth is used to authorize and authenticate between different organizations.
Just my thoughts, and hope to hear more voices.
We have used CAS and SAML in our architecture (Mobile App, Online Portal, and MicroServices) and both are used for different purpose.
Our Online Portal is like online banking that runs in public domain and has to be secure. We don't want to store password and other secure token's in the DB of the online portal, therefore, we use CAS for authentication and authorization. During registration, when user chooses the password, we store the password in CAS and store corresponding token in the DB of Portal
When user login next time, User enters the user name and password in Portal. Portal fetches the token corresponding to user from DB and sends User_name, password, and token to CAS for validation.
But, in case user has already logged in into one application and we redirect user to our another application then we dont want to user to enter username and password again for second application. We use SAML to solve this. First application shares user details with SAML server and gets token in return. First application passes the token to second application. Second application sends token to SAML server to get user details and on success lands user to desired page. Our first application can be Mobile App and second can be Portal in the scenario of App2Web.
Since you have got lot of answers for this question, I would like to suggest you an identity product that can be cater these kind of all protocol in one hand with lot of authentication and user management features. You can just try WSO2 Identity Server version for this.
I'm suppose to build a web application and a mobile application (for iOS) that share the same database. Currently I'm thiking about having a RESTful API and have both applications (web and iOS) comunicate with the API to access data. My problem is the authentication method that I should use. I've been researching about OAuth2.0 but that's not quite the thing I want because I don't want the user to have to authorize the connection as it happens when you log in somewhere using facebook or google+. I just want to make the login with a username and password and then stay logged in. And this for both the apps (web and iOS).
I'm using Node.JS and MongoDB to build the API.
I'm trying to do things "the correct way" because this is suppose to be the final project for my masters.
Can you guys give me some lights in how I can achieve this?
Use OAuth 2.0 so you have an extensible standard and token-based authentication which enables users to revoke authentication tickets, e.g. if their phone was stolen.
OAuth 2.0 supports various grant types. Those that you from facebook and twitter logins can be summarized as '3-legged oauth', but there's also two grant types for 2-legged OAuth, especially the resource owner password credentials grant (section 4.3 at the end of the page) which will simply exchange username and password for an authentication token. There's no need to implement 3-legged oauth if you don't want to.
I'd suggest to use database-stored tokens over crypto-based self-validating tokens for most use cases. The possibility to revoke individual grants, or all grants of specific client applications is super helpful in practice. It also shortens tokens a lot and reduces the risk of a catastrophic security leak because of a flaw in the implementation. Make sure the token itself is crypto-strong random and use a simple crypto-wrapper around the actual token value to enable cheap identification of (badly) faked tokens.
Something like Passport (no, not the whisky, but the middleware) could be a good thing to test
It allows to choose among many different authentication methods in an easy and transparent way
Currently in the process of moving from OAuth1 to OAuth2 in a desktop application for a web service (Imgur), I've been baffled by the OAuth2 specs. Apparently it breaks all the security OAuth1 provided, according to this doc http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified and by looking at different services docs regarding OAuth2.
With OAuth1 you could use a URL to the service where the user would grant access and a PIN was displayed to copy/paste in your app, which was really nice security in the sense that the user never grants their login/password to the app, and can revoke the given access to it at any time through the service's website.
Now with OAuth2 they left this scenario out, forcing the app to request the user's login/password, unless the app makes their own script in their website to receive a token from the service after granting access (then have the user copy/paste it from your website)
Am I missing something here?
Desktop applications can and should use a user agent (browser) to do OAuth and that is described in the OAuth 2 spec under "Native Applications". The flow you described is meant more for devices with limited input capabilities like a gaming console, printer, camera, etc.
AFAIK, the device flow was in the early specs of OAuth 2, but was omitted at some point. Some API providers like Google have implemented limited support for it regardless.
Native applications are the way to go. See the ["Native Applications"][1] section of OAuth 2.0 RFC. The native applications are not intended to store passwords. If you want to avoid entering of credentials directly in the app (even within a browser control), you may do the following from the OAuth 2.0 native application:
Launch the default browser with the authorization endpoint.
Implement a simple web page for your redirect URI, which picks the authorization code and shows it to the user.
Ask the user to copy the code and paste it back in the native application.
Alternatively, the spec suggests that you leverage the URL redirection scheme of the native platform to bring back the original application. You may check iOS and Android's "URL Scheme" capabilities. Unfortunately, neither of these platforms guarantees uniqueness of the URL scheme, hence the authorization code may be hijacked by another rogue app, which is activated on the same URL. I have filed an iOS bug for that.
[1]: https://www.rfc-editor.org/rfc/rfc6749#page-52
Currently we are not using OAuth with our apps but we are working on making the shift, we have direct login and capture the user/pass that was entered and store those. We then turn around and use the stored credentials for a feature that allows the user to open a record within Salesforce.com, we pass the user/pass in to the login endpoint along with a starting URL to the specific record, this works great and is a well liked feature as it is a simple SSO from the App to Salesforce.com where the user can see all data that may not be visible within the app.
Moving to OAuth 2.0 and using the standard webflow, we no longer can capture the user/pass, which is actually a good thing as far as security is concerned. We would however like to keep this functionality, is there anyway of SSO'ing into Salesforce.com by passing along one of the OAuth tokens or some kind of sesson id?
After reading more and thinking about what OAuth accomplishes I feel like this probably isn't possible being that the tokens obtained are meant to be used only with the API and not with the front end system. I hope that I am wrong though and there is a way to login to the front end using these tokens.
EDIT
Ok I am editing to hopefully make this more clear. Currently user's authenticate using the login() API method with their user/pass, we store this user/pass locally (not ideal). We then sync a subset of data that the users can access anytime within the app, being that it is a subset, we have a feature to "SSO" to the Salesforce.com front-end. This simply opens Salesforce.com in a web-view (UIWebView) using the URL https://ns8.salesforce.com/?pw=PASSWORD&un=username#example.com&startURL=/recordId. This will log us in to Salesforce.com and open the specified record.
Moving forward we want to use OAuth 2.0 with the web flow so that we aren't handling the user/pass and so that we do not have to deal with Security Tokens or opening specific IP ranges to allow login without a Security Token.
With that said, is there anyway to use the tokens/credentials received from the OAuth authentication to open Salesforce.com, automatically log the user in, and goto a specific record?
I may have mis-used "single sign on" before, but in a sense, this simulates an SSO from our App to Salesforce.com, in that our users can touch a single button within the app and be logged in to the Salesforce.com web interface.
When you request an OAuth token, you can specify what scope it has, options include api only (the original type of tokens), or other options which include the ability to use the token with the UI pages. (see the scope parameter detail in the help). One of the still missing peices is a way to bootstrap the UI with that token when all you can do is tell a browser/webview to goto a URL, but a widely used (but unsupported) way is via frontdoor.jsp, e.g. you'd open https://{instance}/secur/frontdoor.jsp?sid={the_Access_token}&retURL={optional_relative_url_to_open} remember to URLEncode the 2 values.
So I think you are saying your application uses the SFDC username and password to just authenticate to retrieve a record from SFDC to display in your app?
IF this is correct - which I think it is - then you could just use the standard Salesforce Single Sign On system to authenticate. There is a guide here which outlines the process of setting up a SAML SSO system with Pat Patterson writing an interesting feature on how the security system works here. He has also written a great blog post on DeveloperForce here about the nitty details of OAuth in general for Force.com and not just the SAML setup. I have used the OAuth system in an iPad app against SFDC and it works quickly and easily. I can't see why your system should be unable to use the protocol as you desire.
Direct access into Salesforce is a key benefit of SSO and definitely provided. I'm not sure where you read that SSO in Salesforce is API only. From the SSO PDF pbattisson linked for you:
With single sign-on, users only need to memorize a single password to
access both network resources or external applications and Salesforce.
When accessing Salesforce from inside the corporate network, users are
logged in seamlessly, without being prompted to enter a username or
password. When accessing Salesforce from outside the corporate
network, users' corporate network login works to log them in. With
fewer passwords to manage, system administrators receive fewer
requests to reset forgotten passwords.
OAuth 1 & 2 are both supported, though I'm a fan of OAuth 2 since 1 has really finicky additional steps involving the order of parameters and their encoding sequences. I recently wrote an Apex-Twitter integration and quickly realized it wasn't going to be as easy as Facebook, which uses OAuth 2.0.
But in your case it sounds like you just want to provide users with the ability to actually login to Salesforce and go to a specific landing page once authenticated. This is definitely doable.
Good luck!