OpenID authentication and API access - api

OpenID authentication is inherently browser based. If I wanted to allow an OpenID user to authenticate against an API for use in alternative clients, is there an accepted best practice for that?
So if a user tried to log in with their OpenID into an iPhone app, for instance, how would that work? The only thing I can think of generating an API token of some sort for them and get the user to manually enter it somewhere. This approach is not user friendly.
This is the way sites like Basecamp work, but it still seems clunky to me.

The problem you're seeing is not unique to OpenID. Any password-less authentication scheme can have this problem. OAuth (http://oauth.net/) is a solution that is an open standard that is quickly gaining traction on a lot of web sites. It is totally independent of how the user authenticates, so their OpenID Provider does not need to support or even be aware that your site (the "service provider" in OAuth terms) is using OAuth. Your API client can be web based or even a local application!
The process would be something like this:
Roles:
the user: someone who has an account with your web site.
service provider: your web site, which has a programmatic API that requires some credential to access.
consumer: the client, whether web or local application, that needs access to the service provider's API.
Flow:
The user is at the consumer. He indicates he wants to access data at the service provider.
The user is either redirected (if the consumer is a web site) or a browser is popped up (if the consumer is a local app) and the user sees the service provider web site.
The user is either already logged into the Service Provider via a persistent cookie, or the user must first log into the Service Provider however that is done (OpenID in your case).
The Service Provider then asks the user: "Consumer (some consumer) wants access to your data (or our API, or whatever). Do you want to authorize this? (yes/no)
User confirms, and the browser window closes or is redirected back to the Consumer site.
Via some OAuth protocol magic, the consumer now has a secret credential that it can use to access your API and access whatever user-private information you just authorized.
Obviously I can't include the whole OAuth spec here, but you can see hopefully from the above that this should solve your problem. OAuth libraries exist to make adding support for it easy.
If you happen to be using ASP.NET, I suggest http://dotnetopenid.googlecode.com/ as it recently added OAuth support (v3.0 beta 1).

Neither OpenID nor OAuth define how a user authenticates. They define how the consumer directs the user agent to the authentication provider, how the user agent is directed back, and how the consumer can verify the identity that the user authenticated as.
The actual method used to authenticate is out of band for both schemes.
There are differences between OpenID and OAuth, but both require that the consumer use HTTP redirects and callback URLs. They're both browser based. If your app speaks HTTP, it can do either. However, a main point is that the user is only entering credentials into a trusted app.

What you want is not possible with OpenID. OpenID is based on the premise that you (the iPhone app) only want to know about your users that their OpenID-provider trusts them. They never authenticate themselves to you.
Good OpenID-providers in fact even prevent that you mediate the authentication process (as this would expose users to a possible attack - by you!): they demand that users login with them directly and refuse login-by-referral.

See: this related question
The problem is that the openid spec has no standard provision for authentication with the provider, so the provider can elect that authentication happens via a phone call or whatever.
Hopefully more providers embrace OAuth. Alternatively you could hand code the authentication for a few of the bigger sites.

Related

API server access to third party mobile applications along with User identification

I have to design an IAM solution for a NodeJS microservice using Auth0. Objective is to allow third party mobile application users to access this microservice.
I understand OAuth and OpenID connect solution and one simple solution is third party application accesses APIs as a client using client credentials workflow.
Solution I have to design is allowing users to login and authenticate using their Enterprise IdP connected to our Auth0 Server. So that we can implement authorization and access control at user level.
At the same time customer application needs to be kept agnostic of Auth0 service.
What I mean by it is client should not be required to add any logic in their application for accommodating our Auth0 domain like we have in first party React application. user once logged in to customer application should get access to our API also by using SSO capability. I have read some documents about configuring customer IdP with our Auth0 server acting as a SAML SP. Still I could not understand hows of it and will Auth0 create an OAuth access token in this scenario.
I realise this requires an app to intermediate between customer's mobile app and our API service. Still, I am not able to understand data flow and communication between various components.
Also, I am not sure it is a common situation or requirement? If it is is there any technical term for it? This not seem like a standard B2B scenario.
have to design an IAM solution .. , I am not able to understand data flow and communication between various components ..
Before answering, the answer will points the asked specific questions, may not fit al your needs. SO is not really intended for writing tutorials or searching the documentation. Implementing an IdP (effecively a security module), one needs to do his homework and learn the details.
Maybe using an ready / out of box solution could be interesting. Using an open source IAM such as KeyCloak, WSO2IS could be a quick start. Or cloud services such as AWS Cognito, IBM AppId, Azure AD, .. could be a feasible solution too
a client using client credentials workflow .. access toked received by our API should be for user logged in
The client credentials grant is intended to authenticate only applications. That's it.
To authenticate users, other grant type is needed. For the user authentication the most common option is the authorization code or the implicit grant. The implicit grant is has its weaknesses and is being replaced by the code grant with PKCE (just search it).
End requirement is users of 3rd-party application not required to login again while 3rd-party application fetches data from our API .. Configuring their IdP (most probably Active directory) and our Auth0 servers for the same is all I need to understand
I see most common two options in use:
1. federated SSO authentication
This is the most commonly used option. The external (3rd party) IdP is configured as a "trusted" federated IdP. You often see the scenario when you have a service provider allowing to login with other IdP, often social networks (FB, Google, ...)
The login flow is as follows:
The client authorizes with the provider's (yours) IdP (let's call it IdP1).
IdP1 now acts as as Service Provider with IdP2 (IdP of the partner) and asks for the authorization (redirects the user to the IdP2).
User is authenticated and authorized with IdP2. If the user is already authenticated, the IdP2 doesn't need to ask the user's credentials again, this is how SSO works on this level
IdP2 returns to IdP1 (acting as a service provider).
IdP1 reads the user information (using the id_token, userinfo service - assuming using the OAuth2/OIDC protocol all the time there are other protocols too) and builds its own the user-level token. It may or may not create a local user (it is called user provisioning).
IdP1 returns to the client and the client can request a user-level token.
Then the client can call the API services with the token trusted by the API provider.
2. Assertion Framework for OAuth Authorization Grants
This option is built on top of the Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants, it is an optional extension of the OAuth2 protocol. I call this a token swap service
Basically the token service could validate the access or ID token of a trusted (partner) IdP and issue its own token based on the provided user information.
As you see there are a lot of information and to build a secure solution you ned to make sure that all steps are properly secured (signature, expiration, issuer, validity, audience, subject domain, .. are validated). Disclaimer - as my job we implement IAM/IDM solutions and a lot can get wrong if shortcuts are taken. So you may really consider using an out of box and proven solution.

SSO with JWT and multiple user accounts + SPA

I have two web applications app.domain1.com which is a SPA with his own API on api.domain1.com and app.domain2.com) with each have their own authentication system and user accounts
and I need to authenticate the user from app.domain1.com from app.domain2.com. The goal is to simplify switching from one app to another without requiring the user to log into each application by re-entering their password. I'm the owner of one app only so It's not possible to put them behind a reverse proxy or so.
Example :
app.domain2.com redirect to app.domain1.com/connect/{JWT} -> app.domain1.com SPA extract the JWT and send it via ajax to api.domain1.com for validation and login.
I have looking for OAuth2 and OpenID Connect for these but OAuth2 is more about delegation of resource access than authentication and OpenID Connect needs an Identity Provider which seems incompatible with my use case where each app has his own authentication mecanism and where I could not add a central authentication server.
Ideally, I'd like to adhere to a standard protocol.
I thought I could expose an endpoint GET /connect/{JWT} on each app.
The JWT could contains an email which could identify the user account, app.domain1.com and app.domain2.com could then share the secret for validating the JWT has not be tampered
and could have a short validity duration.
This endpoint validate the JWT, verify if a user match the email inside the JWT and log the user in.
I'm not sure about the security considerations with these process and if there is any other options ?
Thx for your help.
In my opinion you should go with OIDC. That protocol is designed exactly for the feature you described here. You can have one of the apps act as the IdP, and the other will be a Relying Party. It depends on which technology you use for your apps, but in some languages there are libraries which will turn your app into an IdP.
You can think of some generic protocol to make that federated login work, but you will be better off using standards. This way you won't have to wonder what are the security implications for your solution - you have security considerations for OIDC described in the spec itself.

Does github (twitter, stripe & co) uses oauth for its own login?

Does github (twitter, stripe & co) uses OAuth for its own signin/signup forms?
All those authentications are cookie based, so is this regular web client basic auth or does it use some form of OAuth or xAuth ?
On login, a call to https://github.com/session (or https://twitter.com/sessions or https://dashboard.stripe.com/ajax/sessions) is made (with credentials given as formdata) that result in a 302 (or 200 for stripe) with Set-Cookie and a location to https://github.com (or https://twitter.com).
It does not seems that they use a client_id to get a code and exchange it with a token. All the OAuth dance seems striped. And the Bearer header too. So, what's going on here?
Thanks.
OAuth is a three-legged system, two-legs is sort of useless. The whole point of using OAuth is to give other services the ability to perform actions as you without needing to specifically authenticate or pass the data yourself. In the end you must still authenticate against some Auth service.
Since you are using these services as the Authentication mechanism for other sites, it wouldn't make sense to attempt to use it in your own. As part of setting OAuth, the second site redirects to the first and asked to authenticate there, which means you literally need to enter your credentials. Which means that if you are okay entering your credentials into say github, having a different authentication mechanism is useless.
OAuth allows non-github to create user accounts by trusting github with the authentication, or it allows non-github sites to make changes to github as the user once the user agrees to the interaction by logging into github to accept that policy (logging in using their credentials).
Sign in forms on github (and others websites as well) are simply cookie based.
Usually every direct login via the website through a browser is made with cookie based system , simply because isn't necessary to do otherwise.
A bit of theory
Every time you use a login form in a website you are calling an API, not necessarily intended for public use (so a private API)
When you put your credentials in the login form and push that login button , your credentials are being managed by some code in the server that permits you to authenticate against that website.
There is no need for the entire OAuth overhead here because the website has full control on the authentication mechanism and isn't necessary to externalize.
Why OAuth is different in this contest?
OAuth is a system designed to distribute the authentication system across different services / applications even from different vendors.
In OAuth there are multiple actors involved:
the client
the authorization server
the resource provider
In your case all these 3 actors are the website itself and so there is no need for a decoupling system like OAuth.

Can I use extension to pass login and password to OpenID provider?

There will be login page via OpenID controlled by an extension. Can I ask for URL and pass in the extension and then pass it OP by use of extension? If no what kind of data can be transferred to OP from RP by an extension? If yes, how scalable it is, do I have to write separate code of each OP, or will the standard help me?
Also in unlikely case of XY problem - I need some sort of data that will allow me to authenticate OpenID user offline (after at least one successful online login). So if I was the one to provide login and password text fields I would be able to use user's password hash it and use for offline auth. And yes I need to use OpenID rather that other system, because this is the requirement. Sorry, It's kind of ugly problem.
I don't think you're supposed to pass a user id/password to the OpenID provider (or at least not password). The idea behind OpenID is that the provider takes care of the login, thus the web application utilizing OpenID will have no knowledge of the login credentials. OpenID provides you with some authorization information, such as the nickname, fullname, email, etc. This information, coupled with the OpenID of the user itself, should be enough provide you with unique authentication for that user without the need to have a password.
Your application needs to allow the user to go to the OpenID provider's page, enter their credentials there, and once authenticated you will get a response from OpenID indicating whether the authentication is successful and subsequently providing you with the user's information.
Update
Like I mentioned in my comments: the OpenID standard does not define a way in which you can send a password to an OpenID provider. So you can't use the OpenID standard in the manner you're envisioning it.
Update 2.0
Let's take myOpenID for example: in order to use myOpenID as an OpenID provider you have to register your domain with OpenID. Alternately, you can enable OpenID for your website by contacting Janrian (the owners of myOpenID), but I'm going to say you're still going to have to register a website with them. In either case, you must have a landing page on your domain, or on your website, which accepts an authentication response from the OpenID provider (in this case myOpenID). So let's look at what's required:
You must spoof a web browser when you're making the web request to the myOpenID provider.
In that web request, you have fill in the form which takes in the client's password (again, you have to spoof the client doing that).
You have to have a service of some sort running on a website registered with an OpenID provider (such as myOpenID).
You will have to send a message (HTTP) to the service that you're expecting an authentication response for a specific user (and provide it with a way to call you back when the user is authenticated).
That service will take any incoming authentication response from the OpenID provider.
The service will match that authentication with the user ID that you told it to expect in step 4.
The service will send your application the authentication response (callback).
You must accept the authentication response from that service.
The hardest part will probably be step 1 and 2, but there should be plenty of tutorials online that can show you how to do this (sorry I didn't have time to look up specific ones).
In any case, that's how I would imagine you may be able to do this, but it's far from trivial and I've never seen it done before.
Part of the reason why OpenID is so popular is exactly because people don't have to share their credentials with the service provider (i.e. your app), they only share it with the OpenID provider. The other thing you should think about is whether or not users will agree to use the OpenID in the manner that you want them to use it. In other words, one of the main reasons why people use OpenID providers is so that they avoid doing exactly what you're asking them to do: give you their password!
Update 3.0
You can register your domain with myOpenID by going to the new domain registration page: https://www.myopenid.com/new_domain

Which is the better way to implement authentication using login/password AND other social networks?

I'm gonna try to explain my problem :
I'd like to allow users to connect to my api via their own accounts (login/password) or via a social network (Facebook at first).
Then, I would allow any application to use my api, with the user authenticated.
My first thought when to auth the user via his/her login/password and return a token used as the session for the next requests.
But OAuth would seems to be the better implementations, except I don't know how to do this :
One of my applications will have to connect via login/password, like twitter web (I have to implement an login/password auth somewhere if I wan't my user to login :p)
Will I also have to register my applications to the oauth system (did twitter added their web app to their oauth ?)
How to merge the auth via others social networks. Concretely, the user will have to OAuth to my api that will auth to the social network.
I'm a bit lost on how to do this, if someone could help me, I would really appreciate !
Thanks
Update 1:
Flickr and Lastfm seems to not use OAuth but an alternative auth system that looks like this :
The user is redirected to Flickr/Lastfm
The user auth himself and accept to use the application
Flickr/Lastfm return to the Callback url with a temporary frob (for flickr) or token (for lastfm)
The app must call the provider with the temporary frob/token (among with the api_key and the api_sig, as always) and get in return the session token to use for the next calls.
Update 2:
In fact, StackApps is the concrete case of my problem : you can login through their login/password system OR openId, and you can use their API.
OAuth is only needed to make others use your API on other services, i.e. authorize services to use your API without users of the intermediary service explicitly having to log in into your service by giving user's login credentials to a third party.
What I think you need is OpenID, the cross-application authentication mechanism. You just need to implement an OpenID client, accepting third-party OpenIDs to authenticate users, to subsequently identify them, when they use your service's API. This would have to be supplemented with a normal 'local' user authentication mechanism (i.e. login/password entry page)
You will need OAuth to provide an ability to use your API on other sites, though.