Apgigility OAuth2, link between User and Client/AuthorizationCode - zend-framework2

I'm struggling with OAuth2 authorization, authentication and user linking.
What I've done so far:
I've created a client and it's secret.
All redirects and so on are working. Grant type password works for own native app (e.g. Android and iOS)
But for access token, user_id is NULL if grant type is Authorization code.
How can I assign a user to access token or authorization code?
Is there a module for Apigility to provide login screen? I only get asked for "allow" or "disallow" application but I'm never asked for a username and password.
Update:
Question is related to provide OAuth2 access third party pages, e.g. IFTTT. They open /oauth/authorize page and somewhere I have guide user to a login?! to determine related user? Is there an existing module for this?
Third party sites, e.g. IFTTT do not use password grant type for security reasons. And compared to other pages the workflow is: Is user authenticated? Yes: Show Accept/Decline button. No: User has to login and will be redirected afterwards to /oauth/authorize page. So is there a common way in apigility to check if user is logged in and if not, redirect to a login mask?

To authenticate with username and password using OAuth2 you should use the grant_type=password.
I'm not sure if there is a login screen in Apigility. But I don't think it should have it, because Apigility already allow this by one or more endpoints through OAuth2, more specifically by OAuth2 Server Library for PHP.
How to do
Add the grant type to client:
On your client table (oauth_clients.grant_types column) set "password".
Create a new authentication adapter type=oauth2.
Create a post to the authetication url like below.
url=localhost:8080/oauth, where localhost:8080 is where the apigility is running and /oauth is the configured auth adapter url.
payload:
{
"username": "USERNAME",
"password": "PASSWORD",
"grant_type": "password",
"client_id": "CLIENT_ID"
}
When login successfully it will return the access token.

Related

What is the proper Authorization Code OAuth2 flow?

I'm currently unfamiliar with the OAuth2.0 Authorization Code Flow and I've read many articles about it and currently I still don't know how to properly implement it. So far, what I know about the flow:
User Logs in using OAuth
User is redirected to the authorization server for authorization code
Callback for permission/scope
Redirected to authorization server for access token in exchange for authorization code
Redirect back to the client with the access token
Client uses access token to access resource server.
Right now, what I'm still confused is that where should the login validation come (Login of username - password)? Is it a separate validation before going to OAuth flow and once the user is valid, it should go back to the flow?
I have some resources that explain OAuth 2.0 using Google Sign in as an example. Let me try to rephrase it according to your question.
Let's use the example of a user logging-in to Intercom using "Sign in with Google".
The user presses the button "Sign in with Google". This will redirect to the identity providers /authorize endpoint (could be different for each provider) which go to their login page.
The user is redirected to Google's accounts page. If not already logged-in, the user can enter their Google email/password here.
Google redirects back to Intercom with an authorization_code (for example, it redirects to https://intercom.com/authcallback?code=XYZ...)
Intercom's backend server sends this authorization_code with the client_id and client_secret (from their project in google), and receive an access_token (usually to the /token endpoint)
Intercom can then use the access_token to access the user's profile from Google.
So to answer your question, the user can enter their email/password inside the OAuth provider's page. Keep in mind that OAuth 2.0 doesn't specify how the provider is authenticating the user. This means, that the OAuth provider can authenticate their users in different ways, like email/password, email magic-link, SMS OTP, etc. Your website is just supposed to trust the OAuth provider that they are authenticating the user for you correctly.
Some extra resources that would help you understand OAuth 2.0 more:
How to store the OAuth 2.0 access and refresh token in your front end
Picking the right OAuth 2.0 flow
login validation come (Login of username - password)?
OAuth 2.0 NOT an Authentication protocol
The OAuth 2.0 specification defines a delegation protocol
Any use of username - password is outside of OAuth 2.0 and you should be looking at Open ID Connect which is an authentication protocol built on top of OAuth 2.0.
Best current Practice for Authorization Code flow is to use PKCE on OAuth or OpenID Connect.
The usual solution is to externalise both OAuth 2.0 and Open Id Connect from your code by using a mature security library. When you're new to this type of security there is a learning curve. My resources will give you an idea of how it all fits together:
Code Sample
Tutorial Blog Post
The libraries you integrate depend on the technology stack you are using. The resources above are for a Single Page App and NodeJS API.

OAuth 2.0 authorization with my own password

I'm developing an application with OAuth 2 feature. But my case is special. I only want to use my own account to login. Let me take the Facebook as an example to explain the flow of my application:
User start the application
Normally the OAuth will request the user login to his/her own FB account to authorize. But in my application, I want to login to my FB account. Because I know the my own user id and password. Is it a method to login to my account silently?
User is able to post message. In this case, they will post to my FB account.
Is this possible? Do you have any suggestion? Thanks
OAuth 2.0 allows for this type of flow, as defined in the so-called Resource Owner Password Credentials (ROPC) grant. However this flow is less preferred and for backwards compatibility only because it defeats OAuth's primary goal of not having to enter end-user credentials in the client.
FB does not support the ROPC grant so you'll have to go through the regular Authorization Code flow. Once you get a refresh_token through that initial flow, you can use that as a long-lived credential to get new access tokens in the same way that you would use the FB username/password.

Apigility and oAuth for users

I'm about to start working on application with rest API and I want to use apigility. There is one problem unfortunately with this idea. I cannot find reliable source of information how to allow for authentication by oAuth for regular users.
I need to provide access for angular app and native mobile one (possibly in future for third-party web apps). All resources that I have found are about granting access to api for specific client application, not for specific users that use this applications. I don't want to implement two different authentication methods, so if there is a way to resolve this issue with apigility it would be great.
Do you have any suggestions how to approach this? I know that I can generate client id and secret for all registered users but this seams a little crappy solution and I have database schema already in place for storing user info.
What you're likely looking for is the "password" grant type. In this scenario, you will have a way of registering users and their passwords, and then a "login" screen of sorts. This login screen will send the following information:
username
password
client_id -- this will be the OAuth2 client ID (not the user ID!) for the application
"grant_type": "password"
Note that you are NOT providing the client_secret in this scenario! In the case of a user credential scenario, the user's credentials are validated, and then the server verifies that the client_id supports this grant type.
If the user provides successful credentials, then the OAuth2 endpoint will return a token, a TTL, and a refresh_token (which, if you send it before the TTL expires, will give you a new set of tokens).
From here, you will then send the token in the Authorization header: "Authorization: Bearer ". Apigility will then pick this up on each request and validate the token.
The validation returns also the username as part of the identity. This means that you can query the ZF\Mvc\Identity to retrieve the user in order to perform user-specific ACL assertions later!
Poke me on the mailing list (http://bit.ly/apigility-users) if you need some more direction.

OAuth2 - Authorizing against another OAuth sever

I am building an OAuth server and understand the concept of the "Resource Owner Password Credentials" grant method. The user supplies a username and password and the grant_type is set to "password".
However, when the users authenticates using a social network such as Facebook, what grant_type should be specified and what is the suggested flow for handling this type of authentication?
The grant_type would be similar to password, but instead checking the username and password I would be checking the user_id returned from the social network.
I have checked the standard but it does not mention this type of flow.
How should an OAuth server authorize against another OAuth server?
There are different implementations about this. Most of the websites doesn't need any grant_type however, some of them are still using grant_type as password. When the user connects to facebook (installs your facebook app), if the user needs to be registered you can assign him/her a random password or you can still ask the user to register with password. So, the grant_type will be password still.

Oauth2 flow to request a token using Facebook uid for credentials

I am building an iPhone client with a Rails backend. The client communicates with the server through an Oauth2 API. I've set this up using the oauth2 and doorkeeper gems.
Every API request must be sent with a token. I currently support two token "types":
Client: Using the Client Credentials grant type. This is for non-user-specific requests, like accessing app-wide assets, keys, etc.
User: Using the Password Credentials grant type. To get this token, the client must request it by passing a valid username/password combination. All user requests use this token.
This is all working fine but I'm hitting an issue now that I'm allowing a user to also log into the app using Facebook.
Upon the user logging into FB, my client responds by passing the Facebook UID to my server (using a Client token). I then do some checks on my server to match this UID to an existing user in my database.
Here's the issue: I want to respond to this request with a User Token. This token is needed as the user will now be logged into the app, and any subsequent requests will need this token. However, currently I feel like the only way for me to do this is:
Respond with the username and password. Then have the client make a request for a User Token following the Password Credentials flow. I don't like this because I'm passing a password, and it requires multiple trips.
I feel like I may be missing something basic. Is there another way I should be handling this flow?
I think I have a solution but it's definitely a hack.
Basically I'm hijacking the Password Credentials flow to also handle this Facebook scenario.
The client makes the call like so (formatting may be off as I tested in ruby):
curl -i http://www.example.com/oauth/token -F grant_type=password -F client_id=(client id)-F client_secret=(client secret) -F username=(email address) -F password=(password) -F provider="facebook" -F uid=(fb uid) -F token=(fb token)
On my server I check for the "provider" parameter. If found, instead of password authentication it uses the facebook uid to find a match in the user table. I also pass the FB token as a security measure (I verify that this token belongs to the uid before looking for a match). If a match is found, the user is set as the resource owner of the token, meaning I end up with a User Token.
This is the code block from my doorkeeper.rb:
resource_owner_from_credentials do |routes|
if params[:provider]
// FB uid authentication path code here
else
// password authentication
user = User.find_by_email(params[:username])
user if user && user.authenticate(params[:password])
end
end
The resource owner password credentials type defined by OAuth 2.0 doesn't really fit to external logins, e.g., Facebook, since the authentication is done through the external site and not from the username and password on your own authorization server.
One solution is to switch to the implicit grant type of OAuth 2.0 (https://www.rfc-editor.org/rfc/rfc6749#section-4.2). This type is supported by Doorkeeper too.
From your app you have to open a web view and redirect the user to the authorization endpoint of Doorkeeper (default: /oauth/authorize) with the parameters: client_id=..., redirect_uri=... and response_type=token. Additionally you have to tell Doorkeeper to redirect the user to FB login.
Therefore add this to doorkeeper.rb:
resource_owner_authenticator do
user_from_session || begin
session[:return_to] = request.fullpath
fb_login_url = "..." # add here your facebook login url
redirect_to(fb_login_url)
end
end
After the user logged in via FB and you authenticated the user on your server, you have to redirect the user back to session[:return_to] what points to /oauth/authorize and that redirects to the initially given redirect_uri including the access_token in the url.

Resources