How to authenticate for Facebook graph API using standard OAuth 2.0 libraries? - facebook

In a project I am using Authentication multiple times for different providers, so I am relying on standard libraries.
I want to establish connection with Facebook yet it provides not completely standard authorization.
To test the connection I am using REST Console in Authorization part of it I place a key and secret and for
Authorize URL I provide https://graph.facebook.com/oauth/authorize
Access token URL - https://graph.facebook.com/oauth/access_token
Request token URL I leave empty or fill it with https://graph.facebook.com/
And what I get bck looks like this:
{
"error": {
"message": "Expected 1 '.' in the input between the postcard and the payload",
"type": "OAuthException",
"code": 1
}
}
So my question is how to get authenticated forming standard OAuth calls?
EDIT
For the moment (testing stage) I found that data can be retrieved using no standard authentication but access_token with appropriate values. Yet sending http request with api key and secret exposed in the request url can not be the right way of ding it.

Related

POST Requests for CakePHP 3 API are not working

I am developing an API using CakePHP 3.x documentation. To develop this API I am using their official documentation: https://book.cakephp.org/3.0/en/development/rest.html
When I try to access my api using GET request on url http://localhost/healthcare_portal/eapi/applicants/index.json, I get follow expected json result
{
"applicants": [
{
"applicant_id": 1,
"name": "Manender"
},
{
"applicant_id": 2,
"name": "mayank"
}
]
}
But when I access my api using POST request on same url http://localhost/healthcare_portal/eapi/applicants/index.json, I get CSRF Mismatch Token Error. Response from API in this case is
{
"message": "Missing CSRF token cookie",
"url": "/applicants/index.json",
"code": 403,
"file": "/opt/lampp/htdocs/healthcare_portal/eapi/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php",
"line": 191
}
I have tried other alternatives as adding
$input = (array) $this->request->input('json_decode', true);
in my controller's action but this is I get same error on post request. If anyone faced same issue, please help me in getting a breakthrough.
As mentioned in CSRF token mismatch in post request in 3.6 version, the default app template lately has the CSRF protection middleware enabled by default, requiring CSRF tokens and cookies to be sent alongside non-GET requests.
You API should most likely require some form of authentication, and in case that authentication does not rely on cookies, or (HTTP) Basic authentication, or any other form of authentication which browsers/clients will automatically send/perform with HTTP requests, then you don't need CSRF protection, as CSRF would not be possible.
If you don't need CSRF protection
If you really don't need CSRF protection for your API, then you can disable it, for example by using a custom middleware handler that checks the request URL or route and applies the CSRF middleware conditionally, or by applying the middleware on routing scopes, so that you can exclude your API scope, see Cakephp 3.5.6 disable CSRF Middleware for controller.
If you do need CSRF protection
If your API uses a form of authentication that is prone to CSRF, then you should figure out a way to serve the cookies (the middleware will automatically set the cookie on GET requests) and CSRF tokens (they are available on the request object like $request->getParam('_csrfToken')) to your clients, so that they can send them alongside their requests.
See also
Cookbook > Middleware > Cross Site Request Forgery (CSRF) Middleware
https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints

Adding OAuth to a rest api for testing

So I am testing the REST API's given by uber to implement uber service into my app, while sending a request to one of their api it sends me response massage:
{
"message": "No authentication provided.",
"code": "unauthorized"
}
while iam doing the same request as given in their doc
the request iam creating:
headers:
Authorization: Bearer <TOKEN>
Accept-Language: en_US
Content-Type: application/json
to url https://api.uber.com/v1.2/me
where iam getting wrong and what else do I need to add?
In order to be able to use any Uber API endpoint, you will need to authorize your user and get access_token. From your sample code we can see that you did not follow the instructions on Uber documentation. So to make sure you are following full authentication process like it supposes to be please find below info:
The Authorization Code flow is a two-step authorization process. The first step is having the user authorize your app and the second involves requesting an OAuth 2.0 access token from Uber. This process is mandatory if you want to take actions on behalf of a user or access their information.
The redirect URL "YOUR_REDIRECT_URI" is the URL we will redirect back to after an authorization by the resource owner. The base of the URI must match the redirect_uri used during the registration of your application. If none is provided the default is the first redirect URI provided in the application's dashboard
"YOUR_LIST_OF_SCOPES" is the list of scopes you have requested in the authorizations tab. Based what you want to achieve and what API calls you want to make - you will need the certain scope to be used in your two-step authorization process. You can use multiple scopes as comma delimited list.
Please follow the steps of the authentication guide.
Briefly, you need to:
• Send user to authorize url. It starts by redirecting the user to the authorize endpoint: https://login.uber.com/oauth/v2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=YOUR_LIST_OF_SCOPES .
• Receive the redirect with an authorization code. After the user approves the scopes the user will be redirected to the redirect_uri with an auth code that you can post to the /v2/token endpoint to receive an access token.
• Make a POST call to: 'https://login.uber.com/oauth/v2/token'. This call will return access_token and refresh_token.
• After you get your access_token you can use it in the API's endpoints

Authentication with JWT and JSONAPI

I am implementing REST API using the following technologies/approaches:
JSONAPI
JWT token
I want to implement authentication endpoint, it should receive username and password in POST request in JSONAPI format and return JWT token in JSONAPI format.
But I see there are some contradictions that does not allow me to be 100% RESTful:
Let's name endpoint /tokens, because it actually creates tokens. Response would be also resource of type tokens, e.g:
{
"data": {
"type": "tokens",
"attributes": {
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEifQ.ivJ5P23wqVo3w31flg3aOu7er--Ijght_RrBf_MuqsU",
}
}
}
But how about request? username and password are properties of user, but they should be sent to /tokens endpoint. If I send users resource to /tokens endpoint it does not make much sense.
Is there a way around for this, to follow JSONAPI and keep API meaningful?
If I send users resource to /tokens endpoint it does not make much sense.
Why not? REST does not impose that you only send users to a user resource. Sure, when you CRUD operations on a user resource you'll do this via the user resource endpoint.
But to generate a token, it's totally reasonable to send a user resource to the token endpoint.
You could also supply the user credentials via an HTTP Authorization header, or as part of the toplevel meta property of the JSON payload.

FaceBook Auth and signed request

on the client side I am using the flash API to sign in and auth the client
Facebook.init(MyFaceBooyKey, faceBookInit);
Then face book sends back to the client a Signed Request and other stuff.
I the client then sends this signed request to my server.
On my server I process the Signed Request and out pops a FaceBook User id (UID)
So now I am assuming that:
The client who sent the valid signed request is the owner of the Face book UID contained inside it, the client must know the password for that UID, and they are loged into facebook ?
Is this system safe ?
how can i safely use user client side facebook auth to then autho in to a second server, eg a sepreak facebook game server.
How can I make suer that the signed reques has not been coped in transit on the web,
and then sent to me by a thirs party, who now logs on to my server under a Uiffrent UID
How to all theas flash based facebook games auth the users ?
also I note that the same book auth vias the Desktop application dose not send a signed reques ? so how to do the auth to my server in this case ?
All of the auth flows with facebook use SLL (https) and so the data you send/get is secured.
The same goes for all of the graph api requests, if you try to make an api request in http while including an access token you'll get this response:
{
"error": {
"message": "You must use https:// when passing an access token",
"type": "OAuthException",
"code": 1
}
}
If you send the signed request and/or the access token to your server then you should do it by https as well and that way that communication will also be secured.
The client (and I assume you meany the flash client) is not the "owner" of the access token/signed request, your app is the "owner".
If you need the access token on the server side I suggest that you use the Server-Side Auth flow to get it.
If you then need the access token on the client side then you can use a client side auth, since the user already authorized the app and authenticated for sure (through the server side flow) the client side process should be completely invisible for the user, and at the end of it you'll have an access token on the client side as well (a different one than on the server).
"message": "You must use https:// when passing an access token",
"type": "OAuthException",
"code": 1
}
} "message": "You must use https:// when passing an access token",
"type": "OAuthException",
"code": 1
}
} "message": "You must use https:// when passing an access token",
"type": "OAuthException",
"code": 1
}
}

Facebook OAuth 2.0 "code" and "token"

Why do you need both a "code" and a "token" in the Facebook OAuth2 authentication flow as described here: https://developers.facebook.com/docs/authentication/ ?
If you look at the OAuth dialog reference (https://developers.facebook.com/docs/reference/dialogs/oauth/), it seems like you only ever use the token to fetch information about the user, and if you specify the response_type parameter as token or code,token, then you get the token on the first time.
Why do you need to get a "code" and then use the code to get a "token" as opposed to getting the token directly?
I guess I'm misunderstanding something basic about how OAuth works, but it seems you avoid the request to https://graph.facebook.com/oauth/access_token entirely if you get the token the first time with the dialog.
Let us take a simple example to differentiate authentication code vs access token.
You as a user want to try a new Facebook app called Highjack.
So you click on the application and the Highjack app asks you to log into your Facebook account. When you are done, Facebook generates an authentication code for you.
This code is then passed to the Highjack server which uses its own FB client id, FB secret and your authentication code to get an access token.
In the above example the authentication code is confirming you as a user is a valid FB user. But the second steps says "you as a FB user is giving access to the Highjack app for certain resources".
If the Highjack app wanted implicit grant (i.e direct access token), then the access token would be visible to you also since it is being exchanged with the browser. This means you can now call all Facebook APIs on behalf of Highjack using the access token. (You can only use the access token to get your personal information but Facebook has no way of knowing who is calling their APIs.)
Since we have 2 parties (You and Highjack) authenticating with Facebook we have this 2 fold mechanism.
Borrowed shamelessly from Salesforce Documentation:
Authorization Code
An authorization code is a short-lived token representing the user's access grant, created by the authorization server and passed to the client application via the browser. The client application sends the authorization code to the authorization server to obtain an access token and, optionally, a refresh token.
Access Token
The access token is used by the client to make authenticated requests on behalf of the end user. It has a longer lifetime than the authorization code, typically on the order of minutes or hours. When the access token expires, attempts to use it will fail, and a new access token must be obtained via a refresh token.
From the OAuth 2.0 Spec:
The authorization code provides a few important security benefits
such as the ability to authenticate the client, and the transmission
of the access token directly to the client without passing it through
the resource owner's user-agent, potentially exposing it to others,
including the resource owner.
So, basically - the main reason is to limit the # of actors getting the access token.
"token" response is intended primarily for clients that live in the browser (e.g.: JavaScript client).
Answer) You need/want both the code and token for extra security.
According to Nate Barbettini we want the extra step of exchanging the authentication code for the access token, because the authentication code can be used in the front channel (less secure), and the access token can be used in the back channel (more secure).
Thus, the security benefit is that the access token isn't exposed to the browser, and thus cannot be intercepted/grabbed from a browser. We trust the web server more, which communicates via back channels. The access token, which is secret, can then remain on the web server, and not be exposed to the browser (i.e. front channels).
For more information, watch this fantastic video:
OAuth 2.0 and OpenID Connect (in plain English)
https://youtu.be/996OiexHze0?t=26m30s (Start 26 mins)
If you look at the flow of Authorization Code OAuth type, yes, there are actuary two steps:
<user_session_id, client_id> => authorization_code
<client_id, redirect_uri, authorization_code, client_secret> => access_token, refresh_token
In step1: the user tells the OAuth Server that "I want to auth this client (client_id) to access my resource. Here is my authentication (user_session_id or what else)"
In step2: the client (client_id) tells the OAuth server that "I've got the user the authorization (authorization_code), please give me an access token for later access. And this is my authentication (client_id & client_secret)"
You see, if we omit step 2, then there is no guarantee for client authentication. Any client can invoke step1 with a different client_id and get an access token for that client_id instead of its own. That's why we need step2.
If you really want to combine step1 and step2, you can do something like this:
<client_id, redirect_uri, client_secret> => access_token, refresh_token
We use this approach in our Open API Platform, and we haven't find any security problem yet.
BTW, there is actually an Implicit Grant type, that is:
<client_id, redirect_uri> => access_token, refresh_token
It is generally applicable to client only application which have no server backend. In that case, the OAuth server must ensure that the redirect URI belongs to that client (same with the register redirect_uri, for example).
The mix-up came because the user on behalf of himself and not the client app authenticate against the authorization server (i.e. facebook).
Its much simple to secure the client app (with https) then the user-agent (browser).
Here is the original formulation from IETF-oauth (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-threatmodel-08#section-3.4):
3.4. Authorization Code
An authorization code represents the intermediate result of a
successful end-user authorization process and is used by the client
to obtain access and refresh token. Authorization codes are sent to
the client's redirection URI instead of tokens for two purposes.
Browser-based flows expose protocol parameters to potential
attackers via URI query parameters (HTTP referrer), the browser
cache, or log file entries and could be replayed. In order to
reduce this threat, short-lived authorization codes are passed
instead of tokens and exchanged for tokens over a more secure
direct connection between client and authorization server.
It is much simpler to authenticate clients during the direct
request between client and authorization server than in the
context of the indirect authorization request. The latter would
require digital signatures.
Theoretically,
Access Tokens cannot tell us if the user has authenticated but auth code does.
Auth code should not be used to gain access to an API but access token should be.
If you have a single page application or mobile application with no or minimum backend, your application may want to access user's FB data directly at frontend. Hence the access token is provided.
In another case, you may want a user to register/login to your app using some external auth service provider like Facebook, Google etc. In this case, your frontend will send the auth code to the backend that can be used to get access token from Facebook at serverside. Now your server becomes enabled to access user's FB data from the server.
Basically, as an extension of Lix's answer, the access code route allows a Resource Owner (i.e. the Facebook User) to revoke authorization for their User Agent (i.e. their browser), e.g. by logging off, without revoking authorization for an offline Client (i.e. Your Application).
If this is not important, then there is no need to use the access code route.
Furthermore, the access code is provided to ensure that the Token provided to a server is actually registered to the Resource Owner (i.e. the Facebook User), and not the User Agent (or a Man-in-the-Middle).
This seems similar to the question of either choosing the implicit vs authorization code grant flow. In fact, here is what looks like an opposite view point?!.
Also, as Drew mentioned,
When the access token expires, attempts to use it will fail, and a new access token must be obtained via a refresh token.
another piece is the refresh token, but I don't see that being explained too well in the FB Docs. If I'm correct, the implicit grant (the direct token) should be really short lived, but that is to-be-enforced and FB.js seems to hide a lot of that (this one I have not looked as deep into).
If I'm correct, the code%20token is an optimization allowing both the User Agent to have a token and allowing for the server to initiate the token exchange process in a single request (as anything over Network IO is considered expensive, especially to a User Agent).
In OAuth 2.0 with facebook, the overall concept is simple as follows.
Step 1. Obtain "Authorization Code" by a GET request
request URI: https://www.facebook.com/dialog/oauth
Params:
response_type=code
client_id={add your "App id" got by registering app}
redirect_uri={add redirect uri defined at the registration of app}
scope={add the scope needed in your app}
Headers: None
Step 2. Obtain the "Access Token" by sending the authorization code as a POST request
URI: https://graph.facebook.com/oauth/access_token
Params:
grant_type=authorization_code
client_id=<add your "App id" got by registering app>
redirect_uri=<add redirect uri defined at the registration of app>
code=<obtained authorization code from previous step>
Headers:
Authorization:Basic encode <App Id:App Secret> with base64
Content-Type:application/json
Step 3. Use the access token got from above step and retrieve user resources
It’s because the access token is given to an AUTHENTICATED client (third-party app) using a shared secret that only FB and the client knows. The only way that the user could directly request the access token is by knowing the shared secret, which would make the secret public and could lead to a man-in-the-middle attack. Further, while FB can guarantee a secure connection to the user, FB can’t guarantee the handoff of the token to the client is secure. However, FB (and OAuth2) does require a secure connection between the client and FB. The access token is tied to the client public ID (usually hashed), which means only the original client application can use it to request the token because the secret is sent along with the authorization code to get the access token.
You recieve a token when the user logs in. But you might want to change the token when you are performing other actions. EG posting as your app/page or posting as a user with offline_access.