Im trying to use ADFS for SSO on a project. The project is on PHP and Im trying to use OAuth for this.
So what are the steps for setting up ADFS to work with OAuth2? I have no idea about ADFS and cant get any direct guide on OAuth2 settings there.
Thanks a lot.
I see that the question is quite old. But in case if other people will
get here, I have some answer which should be good for March 2019.
Let me start with a general overview.
SSO
SSO could be done with personal Google, Facebook, GitHub, Twitter, Microsoft accounts. After logging in to your account, you can log in to other systems (e.g. WordPress or any other) without password (if other systems integrated with that Identity Provider) and you give the consent (see picture below).
There are services whose main focus is to provide Identity Provider / SSO capabilities (e.g. Okta, Auth0, Google Cloud Identity, Azure Active Directory, AWS IAM).
In the corporate network, the user could be silently signed in based on the AD account without entering credentials via ADFS.
Actually, ADFS supports different authentication protocols like SAML, WS-Fed, and OAuth. But nowadays usually services implement OpenID Connect which works on top of the OAuth 2.0 protocol.
OpenID Connect flows
There is a number of authentication flows that OpenID Connect defines.
Most preferable ones are:
Authorization Code Flow with PKCE (single-page applications, native applications)
If you are using oidc-client-js, you should use response_type=code to use PKCE.
Public native app clients MUST implement the Proof Key for Code Exchange (PKCE RFC7636])
https://www.rfc-editor.org/rfc/rfc8252#section-6
Note: although PKCE so far was recommended as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications.
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-12#section-3.1.1
Implicit flow considered as Not recommended:
Clients SHOULD NOT use the implicit grant and any other response type causing the authorization server to issue an access token in the authorization response
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-09
Client credentials flow. For service-to-service communication.
How to configure ADFS?
You can find quite detailed documentation with illustrations for "Native app scenario" at Microsoft Docs: Native client with ADFS.
If you are not using ADFS, you can play with the PKCE flow setup in the playground.
JavaScript frontend
Never store client secrets in public applications like JS frontend or mobile apps. It's not applicable to PKCE flow but just in case.
If you have a modern SPA application (e.g. Angular or React), it means that frontend should have only client_id to enable end-user to obtain the JWT access_token in a browser via ADFS. You don't need any client_secret.
oidc-client-js could help you with that. Make sure that code_verifier is being sent along with a token request (it means that you are using more secured PKCE flow).
PHP backend
And on PHP side you'll need to validate the access token. You can implement the workflow on your own according to that article. But it's better to use OpenID certified library which you can find on this page (not only for PHP):
https://openid.net/developers/certified/
So, for PHP there is only one: phpOIDC.
Authentication
OAuth 2.0 can help you only with authentication (to identify the user's identity).
Most probably you would like to have different permissions for different users. And OpenID Connect implementation in ADFS provides you the ability to map AD groups to token claims. Therefore, you can decode JWT access token on the backend and implement claims-based authorization.
To use JWT claims be sure to properly validate the authenticity of the token and issuer:
Validate JWT signature using public key
Check issuer for the proper issuer (Identity Provider)
Check aud (audience) for the proper client ID
Check exp (expiration timestamp)
Check claims
Related
I use Google OAuth to sign in my Web Application which was created as a project in Google Cloud Platform i.e. Project1.
I have a user with custom role in this project. After I logged in with my Google account, I'm able to get userinfo using Google_Client (PHP library - google/apiclient). However, I'm having a hard time figuring out how to get the custom role for the logged in user. I tried using Google_Service_iam but get Uncaught Google_Service_Exception: 404 Not Found.
Is this a correct way of building a role based control web app utilizing Google IAM?
Although it would be somehow possible by building it yourself, I would not directly use IAM as an authentication provider. Instead, use the Identity Platform or something like Auth0 or Okta. Myself, I prefer Firebase Authentication, which integrates easily with all popular languages and frameworks.
IAM is meant to authorize users within GCP, and not in a custom web-app. In your setup, you would have to add every future user to Gsuite and IAM, which is very costly and not designed for this purpose.
I would recommend taking a look at the Authentication Strategies for application developers.
Since you need to grant to Google Cloud APIs on behalf of an end user, you may use the protocol OAuth 2.0 protocol. The application initiates an OAuth consent flow where you application will receive the user's credentials. With these credentials, it can call Google Cloud APIs on behalf of the user.
Another solutino as Nebulastic also suggested, is the Cloud Identity Platform, where you can configure custom claims to restrict a user's access to a resource depending on their role.
I have a scenario, we have an PHP based website through which the users login using credentials stored in a database. Now we have another SPA website with .NET CORE as API layer.We don't have an option of having a central authentication server like Azure. If I want to let the users of SPA to access the website since they have already been authenticated in PHP, What should I do? Can PHP generate a JWT to pass it to API? How does that JWT then gets to SPA and how do I validate it? Please be kind as I am a newbie to website programming.
Json Web Tokens are a very specific format for a Bearer token. There are protocols like OpenID Connect that provide more structure around the login and trust process but at their heart, JWTs are just BASE64 encoded json with a verification hash.
You can roll your own SSO with JWT but as with everything in security, rolling your own comes with significant risks of making a bone head mistake and compromising your security. So research research and research some more if you take this route.
I did a very similar thing but stayed purely in the .net world. I used a .net library to build the JWT (https://learn.microsoft.com/en-us/previous-versions/visualstudio/dn464181(v%3Dvs.114)) and ASP.NET Core Identity to handle verification of the JWT (https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer) so I didn't write the code to actually generate the JWT. There is also only SSL connections made between the servers so some of the risk of the token getting sniffed is mitigated.
There are libraries for PHP to generate JWT or you could stand up your own JWT token provider in any language.
There also may be the possiblility of finding an OpenId Connect provider that could hook into your existing database. Identity Server 4 is one for .net but there may be one to be found in the PHP world. This introduces some overhead but does solve the problem of not having the ability to have a third party OpenId Connect provider.
Its not too terrible but security is one place where you wnat to be absolutely sure you get things right.
Authenticating from another server is SSO. There are lots of ways you could do this, but SSO protocols like OpenID Connect and SAML are specifically designed for what you're trying to do.
However, those protocols are anything but simple. You should try to see if you can find existing libraries to have your PHP application act as an Identity Provider (IdP), and your SPA to act as a Service Provider (SP) using the same protocol.
An idea that's a stretch - you didn't explain WHY you can't use a central authentication server. You might consider something like Keycloak (there are other options - that's the one I've used), which you can self-host, and can serve as either an IdP or an SP using OpenID-Connect or SAML 2.0.
You definitely shouldn't build this from scratch on your own (unless this is a hobby project). Authentication is full of security pitfalls that can trip up even the most experienced programmers.
We have an app that uses the OAuth2 Google sign-in system and we want to store data from the users that sign in into our app on our back-end during the initial registration.
This is the way we got it set up:
Users signs in with the app using Google sign-in
We get an ID Token and send this to the server
On the server we verify this token is valid using Google library and save the info we get back from the verification
We also need the user to be able to update/insert data into the back-end when he's authenticated.
After the initial registration, how do we do this?
Do we send the ID Token from client to server each time they call the API on our back-end? In this case how to handle expired tokens?
If you want to make your API a first-class citizen in your system and have it require access tokens that are specifically issued to it instead of accepting Google authentication related tokens that were issued to your client application then you need to have an authorization server that specifically issues tokens for your API.
This authorization server can still delegate user authentication to Google, but then after verifying the user identity it will issue API specific access tokens that better satisfy your requirements, like for example, including specific scopes then used by your API to perform authorization decisions.
For a more complete description of this scenario you can check Auth0 Mobile + API architecture scenario.
In this scenario you have a mobile application ("Client") which talks to an API ("Resource Server"). The application will use OpenID Connect with the Authorization Code Grant using Proof Key for Code Exchange (PKCE) to authenticate users.
The information is Auth0 specific and you can indeed use Auth0 as an authorization server for your own API while still maintaining Google authentication support, however, most of the theory would also apply to any OAuth 2.0 compliant provider.
Disclosure: I'm an Auth0 engineer.
I'm building a REST API using Symfony2 (FOSRestBundle and FOSOAuthServerBundle) and I'm unsure on which grant type to use for this service.
I will have other developers register as users. I was looking at GitHub, and for each user they have a section called 'applications' in their settings which allows adding an application and it gives back client_id and client_secret. But AFAIK GitHub uses the authorization grant type which means you're sent to GitHub to accept and then redirected back to your application with the auth code (does the auth code live forever or what?). I'm not sure if this is what I'm looking for.
What I want is a way to allow developers to consume my API with me knowing who is accessing (FOSUserBundle integrates pretty well here) and what they are allowed to do.
Also, I'll have my own browser based application, Angular.js probably which is the main website where developers can register. It will make API calls to present data for whichever dev logs in. I could use a Node.js backend (need it for some other stuff) so the actual calls are made from there instead as it seems browser only applications aren't really safe. I was thinking of using client credentials grant type from the Node.js backend.
And last, I'll have my own mobile app interacting with the API. Since it's a trusted service it should use Resource owner credentials grant, right?
I'm not sure I understand what you ask for here. As I understand it your developpers will have an account on which they will have to log in in order to use your API. In this case Client Credentials does not seem appropriate, since it would not identify a developper but a client. A client does not represent a user, it represents "an application that accesses your API" (it, in your case you would have one client for your mobile App and one client for your Angular website). I would use a password grant type, that does not redirect you to an external service.
When I had to implement a OAuth2 authentication for my API, I found this article very helpful, it is based on a Symfony2 example but most of the explanations apply everywhere.
I am developing rest apis in symfony application.
Right now my apis are used by my application only on frontend (ajax requests by Angularjs). In future I would like to expose same APIs to third party applications as well.
Also I will be having have Android, IPhone apps etc in future.
I have integrated FOSOAuthServerBundle, and have tried all grant type workflows. Its all working. But I am confused about can these be used by my application or are they for only 3rd party applications who like to integrate with my application ?
I understand how these workflow can be used by 3rd party apps. But really can't understand how can I authenticate my native application users ?
I want to know how to use this bundle to authenticate users on my website through rest apis from my frontend app ?
Currently I am usnig FOSUserBundle and form_long to authenticate user but I am changing frontend to use Angularjs and rest based. So ideally authentication should just work like form_login authentication but it should be rest based.
I did research on it and people suggest to use "Resource Owner Password Credentials" But it needs client secret to be exposed in javascript which may not be secure
It should work e.g. user submits username/password credentials like it works in case of form_login but instead of redirecting it should just return access_token.
Do I need to write my custome authentication provider which uses UsernamePasswordToken and firewall listener like OAuthListener which returns access_token ? Would that be secure to use?
The similiar question with some discussion here:
Symfony2 FOSOAuthServerBundle grant type password requires client secret
If you don't want to expose secret, use a proxy beetween your front-end angular code and actual OAuth server. Anyway, if you expose secret it still needs user credentials.
You can set allowed grant types to each OAuth client, so in case you create mobile apps, you'll want to generate a separate pair of client_id & client_secret for the app and for the front-end, with the only allowed grant type of "password" for the front-end app.