Shared authentication for web services - authentication

Our company, Company A, may soon be partnering with Company B under some sort of licensing agreement. If it goes through, it will be necessary for users of Company B's web service to have access to Company A's web service. In other words, any user with an account for Company B's service should automatically have an account with Company A, but without having to create a new account...their's should be a shared account.
I'm not an expert in this matter (obviously) but I think this scenario would call for something along the lines of OpenID, but just between our two web sites. How would we go about sharing authentication is this way? I'm not familiar with the verbiage of the subject, which makes it difficult to google for guidance. Would this be a single-sign on?
Thanks.

You're really describing federation here, of which OpenId is one example (albeit one that's not suitable in this case). With federated identity Company A allows Company B to authenticate their users. This authentication process results in a token from Company B containing information (claims) about the user which is sent to Company A and used for authorisation.
Federation is not single sign-on, that tends to describe the situation where Company A runs lots of services and an authentication service as well - and logging into the authentication service allows a user to access all of the resources without having to re-authenticate.
Without knowing what the architectures involved are it's hard to recommend an approach. The standard way to transport claims is in a SAML token. In a Microsoft environment you can use the Windows Identity Framework to write web services which understand SAML, and ADFS "Geneva" to issue SAML tokens from an Active Directory. There are similar solutions for other identity stores, such as IBM's Higgins.

I don't think OpenID is really an answer here. It matters very much how users of B's web service currently authenticate to these web services. I assume that they use username/password pairs, and assume that you want them to continue doing so even for A's web services.
If so, the next question is how the password gets transmitted and validated. I assume that B currently uses "Basic Authentication" (you need to confirm this with B). If so, authentication is straight-forward in principle: In an A web service, also use basic auth, which causes users to send their passwords to A, IN PLAIN TEXT. Use https to encrypt the passwords on the wire.
Then, having a copy of the password, validate them with B, e.g. by having A's service sending a request to some dedicated service at B which just confirms the password as correct.
The downside of this setup is that users have to reveal their passwords to A; by means of the licensing agreement, you need to establish trust that A won't abuse these password (i.e. that they will not store them, and not use them to incarnate a user outside of the agreed processes).

You have two problems, I think.
Allow Company A machines to authenticate Company B users (and vice versa?)
Provide resources on Company A machines for Company B users.
Single sign on, or any authentication solution like OpenID, solves the first part (and may be sufficient for static content); you still will need to actually create accounts or otherwise allocate resources on Company A machines for these now authenticated users.
For example, StackOverflow uses OpenID to authenticate users. This means that StackOverflow can leave the part of figuring out who you are to other services, such as Google or Facebook etc. However, StackOverflow still needs to create a local account for you, to track your reputation, send you updates to your questions, and other things.
For just the authentication part, here are a couple of options:
If Company A already support OpenID, then Company B could just be an OpenID provider. You would still also want to add some code to Company A's website to ensure that a user logging in with OpenID is authorized, i.e., from Company B.
If Company A and B both use LDAP (e.g. Microsoft Active Directory) to handle authentication for internally, then you can probably add a forwarder to have Company A query Company B's LDAP servers to authenticate users (subject to appropriate firewall tunneling).
Or you can do it more statically, by having Company B provide a list of users, and having Company A pre-create accounts for all of those users ahead of time. This is the simplest but doesn't handle change of personnel from Company B very effectively, unless you set up an additional synchronization process. Here you would probably generate passwords (e.g., lastname+employeeID or random strings) for each account and have Company B distribute them to its users.

Related

How do you authenticate a third party developer to access your API via oAuth 2.0?

Suppose I have a working REST API for my product.
I want to give access only to developers who sign up to this product. Also, there will be several plans available so certain parts of the API are not accessible on the free plan.
From the grant types I've seen only the client-credentials one seems to be the closest solution. However that won't authenticate the developer account stored in my product db, it will only get an access token for that client. The user won't actually be 'logged in' per se. Add to that the fact that a single client can be reused by everyone, according to implementations I've seen.
The only way I see is creating a custom grant type, by adding an extra api_key to the client credentials type, which pertains to the developer account.
Is there a way to do this with the existing grant types? Introducing custom types will not work with many oAuth2 libraries out there out of the box and I don't want to give the developers the hassle of modifying them.
I don't think you have to invent a custom grant type.
A single client can be reused by everyone only if everyone knows the client secret.
So, it seems that what you have to do is (1) to authenticate a developer when you issue a pair of client ID and client secret to the developer and (2) to motivate the developer not to reveal the client secret to others.

How to represent real users and other apis with OAuth?

I have an API which I'd like to secure using OAuth. My API is accessed with a web frontend used by real human users all with their own account (a couple of thousand), and it is also used by the API of some partner companies (less than a hundred), which should also have separate accounts.
I would like to secure the API using OAuth, and I have to decide how to represent the different users. In OAuth, there are two different concepts, clients and users, where client is the higher level concept, and every user is under one of the clients.
I can think of two different ways to represent these API accounts:
Have a single client, and have a separate user for every human user, and for every partner API.
Have one client for the human users, and a separate user for every human user. And have a separate client for every partner API.
Which of the two approaches would be the more idiomatic approach in OAuth? From a technical standpoint I don't see too much advantage or disadvantage of either solution.
(I'm partly confused because the client credential flow is described to be used for API-to-API authentication, which seems to make sense for authenticating the partner APIs. However, most of the OAuth guides also say that it should only be used for trustful APIs (whatever that means), or even internal APIs, but these partner APIs are definitely not internal.)
Implementation will be unified if there is separate client behind every app (including JS one, for users accessing your API via web frontend).
Also it will be possible to manage ACL per app in this case, which will define maximum privileges for the users (users may choose to give less privileges to the app).
On the other hand, simpler approach is to use Cookies for web frontend users and OAuth for partner applications. But in this case you need to support both authentication options.

Secure PHP REST API

I am making a Social Networking website and I want to provide APIs for developers to use. So, I am thinking of using REST API for this.
Now this question is not about how to create a REST API. That is well explained in many websites and SO questions.
My Question is:
When I give a developer this API (lets say which can be used to get user info).
Say USER 1 does not want his date of birth and email to be visible
Say USER 2 does not want his mobile number to be visible
Say USER 3 does not want anyone apart from his friends to see his info
... and so on (each user have their own privacy setting which I have already stored in DB)
Now, how do I authenticate properly to make sure:
1) Developers will not be able to access User info when they have not authenticated the Application to use API to access their info
2) Restrict Developers from accessing fields which has been set by the user as private
Do I have to make separate DBs for this? Is there any easy, professional and secure way to do this?
If you look at the documentation for the various Google+ and FB API's, you'll see what they do. Here's an example:
https://developers.facebook.com/docs/marketing-api/authentication
Generally, you use https to connect, you supply a couple of different key codes (api key, etc.) to an authentication call of some sort, and you get back a session token, which you pass to all subsequent calls that require one (which potentially involve non-public data).
There isn't anything all that special about the authentication that is typically used for this kind of thing, any secure authentication method works as well as any other. All authentication does is establish the identity of the API caller and/or the identity of a user. It is then up to the API code to determine who can access what.
You could have a small group of trusted developers develop the API in a development environment, and then an even smaller group of trusted administrators deploy that API to production servers, and make sure no one else can access those servers except through the API. I believe that's essentially what FB and Twitter and so forth do.
But if you really want to prevent the developers who develop the API and the administrators who set up and maintain your production servers (and databases) from being able to get at user's private data, that data will have to be encrypted on the users' computers, before it is ever sent to the server, using keys that are never sent to the server. So neither the server nor anyone in the server environment will have any way at all to decrypt that data.
But the developers who develop the encryption program that runs on users' computers could make it send keys or decrypted versions of data to a computer somewhere, etc., so there isn't really any way to avoid having to trust at least some of the people involved.
By the way, Google+, Twitter, Facebook, etc., don't do that. They may store some private data in an encrypted form in their production databases, and they may restrict access to those databases to a small group of people, and even those people who have access to the databases may not be able to see the private information without decrypting it - but the data is sent to the servers using https; it is encrypted by a user's browser, but then decrypted on the web server, and it exists in an unencrypted form in the memory of the web server, at least for a short time, so it would certainly be theoretically possible for people at those companies who have the right expertise and the right access to get at users' private data. So our private data on Twitter / FB etc, isn't really 100% secure. (I doubt that any data anywhere is really 100% secure.)
While there are common practices that you can glean from reading their API docs, there aren't really any established standards or best practices that specifically relate to how to code authentication systems for social media APIs in PHP.
It's worth mentioning that many web sites that require user authentication, these days, allow users to authenticate using various external authentication systems, so that once they are signed into one place that uses that system, they're effectively signed into every place that uses it. One really popular external authentication system is GoogleID; for example, users of Stack Overflow can authenticate using their Google logins:
https://developers.google.com/identity/
https://developers.google.com/identity/choose-auth
GoogleID may have been inspired by OpenID. Here is a list of libraries for implementing an API that facilitates OpenID style authentication:
http://openid.net/developers/libraries/
That page includes a couple of php libraries which may be of interest.
By the way, speaking of data security in the context of a social media site, here's an introductory wiki page about the general legal requirements, in the US, for companies that process (potentially) personally identifying information:
https://termsfeed.com/blog/privacy-policies-are-mandatory-by-law/

How do multiple websites get same unique identifier from the same OpenID user/identify?

We have a backend (RESTful) service for websites that depends upon uniquely identifying the same user across multiple, unrelated websites. We have been using email address as the unique identifier, but email address is not always used by all websites, especially when OpenID authentication is by those websites.
So, does OpenID provide a unique identifier that would be the same across multiple Relying Parties (if the user authenticates with the same OpenID)?
If so, what would one instruct a series of independent website to provide us as a user identifier for each of their users if the goal was that multiple, unrelated websites provide the same identifier when they each have the same OpenID user?
Also, a goal is to make this as easy as possible for developers that will consume our APIs. So, if you know of any good API documentation that has already solved this, links to that would be very helpful.
Without knowing anything about your web service or what language its written in, I'm not certain how helpful my answer will be as it will be fairly general and less technical.
OpenID providers responding to an identification/authorization request will respond with a "Claimed ID" and an "Identity" as well any "attribute exchanges" requested. The attribute exchange information can be things such as email/username/language/realname/etc that may be what you are looking for.
Google (as an OpenID provider) supports querying a decent number attribute exchange information, and provides a list in their documentation:
https://developers.google.com/accounts/docs/OpenID#Parameters
The OpenID Identity should be unique to a user, but may not cross-identify them to different websites even when issued from the same provider. (It can be a directed id unique to the RP it was issued to).
See more on this here:
is openid.claimed_id static?
With all of this said, it is perfectly reasonable for you, as the designer of the API, to define that certain information (i.e. an email address) is required to consume the webservice. And then leave it to the parties that wish to use your webservice to somehow gain that information (directly asking a user, or through attribute exchange, etc).
For more information on OpenID I would look at their website, particularly the specifications and libraries:
http://openid.net/specs/openid-authentication-2_0.html
http://openid.net/developers/libraries/
Libraries with some good documentation to use as a starting point include:
JOpenID (Java): http://code.google.com/p/jopenid/wiki/QuickStart
LightOpenID (PHP): http://code.google.com/p/lightopenid/w/list
Implementing the OpenID authentication directly would not be applicable for a backend webservice since the end user has no involvement (i.e. could not supply credentials).
To meet your requirement of identifying the same user across various 3rd party websites you may need to become an OpenID provider. And then provide further API to allow functionality on 3rd party websites for users to link into their OpenID profile you manage.
Without being the actual provider of the identity... Sharing the OpenID identity with a 3rd party may be a potential security/privacy concern or in the very least against the specs of OpenID (which describes the exchange as a a shared secret between the RP and OP). Though it may be beyond the scope of what you wanted to do, being the OpenID provider would at least remove many of the privacy issues since the users would have to opt-in explicitly.
I'm not aware of any APIs that handle uniquely identifying users across multiple 3rd party websites without direct user interaction. Most webservices that I have written required either direct user credentials be supplied (for which the user was aware), or had to only identify a user as unique to a particular client. In the later case user authentication is not always necessary, the client could do a blanket authentication and then provide its own unique ID to track users, letting the the webservice be blind to what actually constitutes a user. Your requirements do not appear to fit into these common scenarios unfortunately.
One final thing to consider as you design your API...
Providing uniquely identifiable information (i.e. an email address) to a 3rd party may raise some eyebrows in the internet privacy ring. Especially if there is any financial gain to be had from the exchange (advertisments/directly-paying/etc) or if the use of the information is unknown/insecure or otherwise unwelcome.
http://www.ehow.com/about_5332990_legal-sell-email-list.html
http://www.aclu.org/technology-and-liberty/internet-privacy
You may want to ensure that your target clients (the consumers of your webservice) have the right jargon in their terms or can provide sufficient power to their users that allow them to opt-out of being submitted into your service. And make it clear what you are doing with the information...
Issues like that can be something that holds up acceptance of your API, so it is worth considering.

Storing users of a public web site in Active Directory

I am working on a system architecture for a fund/pension manager. We are providing two ASP.NET MVC web applications; one to allow members of the pension fund to login and check their balances, manage their investment, etc and another to allow employers to make contributions to the fund on the employees (members) behalf. There are also internal applications delivered via the intranet.
We have been considering using Active Directory for storing, authentication/authorisation of not just the internal users (who are already using AD for logging into the domain and resource authorisation) but for the member and employer user accounts. The member and employer user accounts would be located in a different hierarchy (maybe even a different AD instance?) to the internal users.
However I am wondering if this is the best use-case for AD... given AD is such an 'internal' resource, should it be used to hold auth details for 'external' users (the alternative being a USERS table in a database)?
The benefits are: AD is designed and optimised for holding this sort of data, ASP.NET apps integrate with AD authorisation easily, there possibly are existing tools for working with the data (password resets, etc).
What are the risks?
I would recommend against a hybrid of internal and external users. Speaking from experience it opens a lot of security headaches. It might be better to create separate authentication systems, one that uses AD directly against the internal domain and another that uses an ADAM directory designed simply to hold external users. (i.e. - internal users should be authenticated using NTLM with the AD to ensure a kerberos encrypted login, while forms would be usable for the ADAM instance).
AD is very easy to integrate though, and if direct integration is undesirable due to the networking lumps, you can always attempt an LDAP:// to achieve the same authentication results.
I think your biggest risk is that AD would not scale to the amount of users you might have from an Internet app. I would use the Membership provider, unless you are trying to achieve SSO with internal and external accounts.