Sign In With Apple - App Access Token Support? - swift

I'm just looking at migrating an existing Login with Facebook flow over to Sign in with Apple with the hope of eliminating FB Login entirely from our iOS app.
The client side seems straight forward enough, however there's one topic I can't seem to see any documentation or discussion on Stack Overflow about - a Sign In with Apple equivalent for FB App Access Tokens.
Facebook Login supports different token types (https://developers.facebook.com/docs/facebook-login/access-tokens/) and currently our app back end supports 2 authentication flows.
From End App Users, they Login with Facebook, send the provided client User Access Token to the app backend which validates the token against Facebook and then issues an app specific JWT token to the app client that is used in further app API calls until expiry.
From backend server components. These request an App Access Token from Facebook e.g.
curl -X GET "https://graph.facebook.com/oauth/access_token
?client_id={your-app-id}
&client_secret={your-app-secret}
&grant_type=client_credentials"
The App Access Token is then send to the app backend which validates the token against Facebook and then issue an app specific JWT token that is used in further server to server API calls until expiry.
Replacing 1 above seems straightforward but what about 2? Is there a mechanism for achieving the same flow with Sign In with Apple?
It seems like the https://developer.apple.com/documentation/signinwithapplerestapi would be the API to use for validation but is there a way to generate an App Access Token equivalent for Sign In with Apple in the first place to validate using this REST API?
Thanks

I think it's possible
I'm not exactly sure how to really use it or validate it yet, but you get an access_token in the response from https://appleid.apple.com/auth/token when Generating and Validating Tokens
Getting an access_token from Apple
This example assumes you have an Authorization Grant Code, but the same is possible if you have a refresh_token, etc. instead.
Prepare a POST request to https://appleid.apple.com/auth/token
Fill out the following key-values as x-www-form-urlencoded:
client_id
client_secret
code
grant_type
redirect_uri
If successfull, this will return:
**access_token**
token_type
expires_in
id_token
I'm not sure if this is the type of access_token you're looking for, but I wanted to bring it to your attention.
It may be useless for now
After writing this, I came across this thread in the forums where Apple said:
Currently, the access token only indicates a successful refresh token validation. There are currently no endpoints where it can be used and it is reserved for future use. So, it can be ignored for now.

Related

How does one get the app access token for debug_token inspection on Facebook?

It is suggested that whether your app uses code or token as your response_type you should perform an automated check on the access_token to confirm that the token belongs to the person the app expects it to belong to and that it was your app that generated the token.
You are supposed to do this on
GET graph.facebook.com/debug_token?
input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
where app-token is app_id|app_secret and token-to-inspect is the user's access_token. Also, I think from reading the documentation you can retrieve an app-token by doing a client-credentials call with the app_id and app_secret.
This is fine with an authorization flow implemented server-side, but what if you're using the implicit method and chose response_type as token (and for whatever reason aren't using FB's javascript SDK)? How do you safely get that app-token without leaking your app_secret? How does FB's SDK do it?
You can generate an app_token in your Facebook developer panel here
and then simply save it into a config file server side. From the developer's page:
App tokens do not expire and should be kept secret as they are related to your app secret.
On my page, I use the following flow:
The user authenticates with the Facebook JS SDK, and then sends his
token + uid to the server.
The server validates that the given token
is related to the given person via a call to the "debug_token"
method, that you spoke of.
If the token + uid combination is valid,
it authenticates the user server side.
I hope this helps.

Facebook App Login - Exchanging code for an oauth access token is working only once

I'm using the URL below to get the auth token:
https://www.facebook.com/dialog/oauth?client_id=CLIENT_ID&redirect_uri=RETURN_URL&scope=manage_pages,publish_stream
This page will redirect to another URL with the code token in query string. I'm using this code token to get the Page access token automatically and publish to the Page 'offline'.
In recent days, it seems that Facebook has changed the expiration time of this token code.
I am able to use this token once. The time expiration is very short. Anyone know if there really was a change in facebook? Is there any other alternative to work with this?
This was part of the December 5th changes on the Roadmap: the code can only be exchanged for an access_token once and must be exchanged within 10 minutes of generation.
New security restrictions for OAuth authorization codes We will only
allow authorization codes to be exchanged for access tokens once and
will require that they be exchanged for an access token within 10
minutes of their creation. This is in line with the OAuth 2.0 Spec
which from the start has stated that "authorization codes MUST be
short lived and single use". For more information, check out our
Authentication documentation.
If you're unsure how to log users in correctly because you were relying on the old, incorrect behaviour, ensure you're using the newest SDKs and read the Login documentation in detail, specifically the Server Side Login documentation which shows how to exchange the code for a token
Once you have the token, save it using whatever session storage mechanism your app uses (PHP SDK will store it in a PHP session for you) and use the access token on subsequent calls instead of trying to obtain a new access_token from the code

REST API for website which uses Facebook for authentication

We have a website where the only way to login and authenticate yourself with the site is with Facebook (this was not my choice). The first time you login with Facebook, an account gets automatically created for you.
We now want to create an iPhone application for our site and also a public API for others to use our service.
This question is about how to authenticate with our website from the app/API and is broken into 2 parts:
What is the correct way to handle REST authentication from an API to a website which only uses Facebook OAuth as an authentication method?
I have read and researched a lot about standard methods of authentication for REST API. We can't use such methods as Basic Auth over HTTPS, as there are no credentials for a user as such. Something like this seems to be only for authenticating applications using the API.
Currently, the best way I can think is you hit an /authorize end-point on our API, it redirects to Facebook OAuth, then redirects back to the site and provides a 'token' which the user of the API can use to authenticate subsequent requests.
For an official application that we create, we wouldn't necessarily need to use the public API in the same way. What would be the best way then to talk to our website and authenticate users?
I understand (I think) how to authenticate 3rd-party applications that are using our API, using API (public) keys and secret (private) keys. However, when it comes to authenticating the user who is using the app, I am getting rather confused about how to go about it when the only way we have to authenticate a user is Facebook.
I feel like I'm missing something very obvious, or don't fully understand how public REST APIs should work, so any advice and help would be greatly appreciated.
UPDATE: see below
I've been thinking hard about this question too. It's not entirely clear to me yet but here's the route I am thinking of going. I am creating a REST API an my users only auth with Facebook connect.
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
In every call to my custom API I'll include the Facebook user id and the access token.
On the API (for every method that requires user authentication):
Make a request to the /me Facebook graph using the access token from above.
Verify that the Facebook user id returned matches the user id passed to my API from above.
If the access token has expired additional communication is required.
I have yet to test this. How does it sound?
--- Update: July 27th, 2014 to answer question ---
I only use the above exchange once upon login. Once I determine which user is logging in, I create my own access token, and that token is used from that point going forward. So the new flow looks like this...
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
Request an access token from my API, including the Facebook token as a parameter
On the API
Receive access token request.
Make a request to the /me Facebook graph using the facebook access token
Verify that the Facebook user exists and match to a user in my database
Create my own access token, save it and return it to the client to be used from this point forward
This is my implementation using JWTs (JSON Web Tokens), basically similar to Chris' updated answer. I have used Facebook JS SDK and JWT.
Here's my implementation.
Client: Use Facebook JS SDK to log in and get the access token.
Client: Request JWT from my API by calling /verify-access-token endpoint.
MyAPI: Receives access token, verify it by calling /me endpoint of Facebook API.
MyAPI: If access token is valid, finds the user from database, logs in the user if exist. Create a JWT with required fields as payload, set an expiry, sign with the secret key and send back to the client.
Client: Stores the JWT in local storage.
Client: Sends the token (the JWT from step 5) along with the request for the next API call.
MyAPI: validate the token with the secret key, if token is valid, exchange the token for a new one, send it back to the client along with the API response. (No external API calls for verification of the token here after) [if the token is invalid/expired request client to authenticate again and repeat from 1]
Client Replaces the stored token with the new one and use it for the next API call. Once the token expiry is met, the token expires revoking access to API.
Every token is used once.
Read more answers about security and JWT
How secure is JWT
If you can decode JWT how are they secure?
JSON Web Tokens (JWT) as user identification and authentication tokens
I am trying to answer the same question and have been going through a lot of reading recently...
I won't have "the" answer but things are getting a little clearer for me. Have you read the comments in the article you mentioned? I found them really interesting and helpful.
As a result, and in the light of how things have evolved since the first article has been written, here's what I think I'll do:
HTTPS everywhere — this allows you to forget about HMAC, signing, nonce, ...
Use OAuth2:
When authentication requests come from my own apps/website, use this 'trick' (or a variation of it) described in a reply to the article mentioned before.
In my case, I have two types of users: those with classic login/password credentials and those who have signed up with Facebook Connect.
So I'd provide a regular login form with a "Login with Facebook" button. If the user logs in with his "classic" credentials, I'd just send these to my OAuth2 endpoint with a grant_type=password.
If he chooses to log in via Facebook, I think that would be a two-steps process:
First, use Facebook iOS SDK to open an FBSession
When that's done and the app is given back control, there should be a way to get a Facebook ID for that user. I'd send this ID alone to my OAuth2 endpoint with an extension grant understood by my server as "using an FB User ID".
Please note that I am still heavily researching on all this stuff, so that might not be a perfect answer... maybe not even a correct one! But I think that would make for a good starting point.
The idea of using an "extension grant" for the Facebook authentication might involve having to register it to do things properly? I'm not quite sure.
Anyway, I hope I was able to help you even a bit, and that at least it can start a discussion to find the best solution to this problem :)
Update
The Facebook login is not a solution as pointed in the comments: anybody could send an arbitrary user ID and log in as this user on the API.
What about doing it like this:
Show a login form with a "Facebook login" button
If this login method is chosen, act kinda like the Facebook SDK: open a web page from your authentication server, which will initiate the Facebook login.
Once the user has logged in, Facebook will use your redirect URL to confirm; make that URL point to another endpoint of your authentication server (possibly with an extra parameter indicating the call came from an app?)
When the authentication endpoint is hit, the authentication can securely identify the user, retain its FB User ID/FB Session and return an access token to your app using a custom URL scheme, just like the Facebook SDK would do
Looks better?

Facebook access token: server-side vs client-side flows

Facebook docs:
Facebook Platform supports two different OAuth 2.0 flows for user login: server-side (known as the authentication code flow in the specification) and client-side (known as the implicit flow). The server-side flow is used whenever you need to call the Graph API from your web server. The client-side flow is used when you need to make calls to the Graph API from a client, such as JavaScript running in a Web browser or from a native mobile or desktop app.
What is the difference between access tokens taken by these flows?
It seems like they length differ.
Can we use server-side flow token on a client? And otherwise, can we use client-side flow token on a server?
Currently, Facebook says this about access_tokens. On Server-side OAuth
if the access_token is generated from a server-side OAuth call, the
resulting access_token will have the longer expiration time by
default. If the call is made while there is still a valid long-lived
user access_token for that user, the returned user access_token from
this second call may be the same or may have changed, but in either
case the expiration time will be set to a long expiration time.
Where as client-side OAuth flow will give you a existing, non-expired, short-lived user access_token. To make this access_token long lived, facebook is providing a new endpoint that exchanges the short lived access_token with an access_token with longer life. The endpoint is
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
Also please note that
Currently the long-lived user access_token will be valid for 60 days
while the short-lived user access_tokens are currently valid from 1 to
2 hours.
Excerpt from https://developers.facebook.com/docs/roadmap/completed-changes/offline-access-removal/
For those that like me are facing the same issue in 2014, Facebook improved the documentation on access tokens.
Tokens are Portable
One important aspect to understand about access token is that they are portable. Once you have an access token you can use it to make calls from a mobile client, a web browser, or from your server to Facebook's servers. If a token is obtained on a client, you can ship that token back to your server and use it in server-to-server calls. If a token is obtained via a server call, you can also ship that token down to a client and then make the calls from the client.
(from https://developers.facebook.com/docs/facebook-login/access-tokens/#portabletokens)
So yes, you can use access tokens from the client on the server and vice-versa; as already stated by naveen, the difference is that client-obtained tokes are short lived, whilst server ones are long lived. You can also convert a short-lived token to a long-lived token by following the directions here: https://developers.facebook.com/docs/facebook-login/access-tokens/#extending
Token can be used to make API calls since it represented that you are authenticated and authorized to do something.
Code can not be used directly to make any API call. It must be first redeemed with your app secret to get a token.
In other words, code is like an encrypted token that only parties with app secret can decrypt it.
BTW, your app secret should only appears in your server code, never in mobile or web client.
The video basically explains all this at around 13:00
https://developers.facebook.com/docs/facebook-login/security
A user access token (and page access token) will be the same in either server-side or client-side environment (other than maybe for the time stamp expiration).
An app access token will be exactly the same either server-side or client-side.

ColdFusion Facebook Integration

I have an app with a login screen with a button that invites users to login using facebook.
That authentication part of the integration works fine. I have also parsed the returned cookie variable to obtain the userID. The next step is to obtain the users information.
I found this stackoverflow article Difficulty parsing string with Facebook one click sign on and ColdFusion which says
Once you get parsed signed_request (stored in your cookie) you can use
user_id (which is Facebook User Id) and oauth_token (aka access_token)
to get needed info via Graph API or FQL.
But, how do you obtain the access_token the poster speaks of? It is not in the cookie variable (that I can see anyway).
Sorry for being such a noob. I got twitter working easy. Facebook is a pain.
https://developers.facebook.com/docs/authentication/ is your friend. Read the server side flow section.
"If the user presses Allow, your app is authorized. The OAuth Dialog will redirect (via HTTP 302) the user's browser to the URL you passed in the redirect_uri parameter with an authorization code:
http://YOUR_URL?code=A_CODE_GENERATED_BY_SERVER
With this code in hand, you can proceed to the next step, app authentication, to gain the access token you need to make API calls.
In order to authenticate your app, you must pass the authorization code and your app secret to the Graph API token endpoint - along with the exact same redirect_uri used above - at https://graph.facebook.com/oauth/access_token. The app secret is available from the Developer App and should not be shared with anyone or embedded in any code that you will distribute (you should use the client-side flow for these scenarios).
https://graph.facebook.com/oauth/access_token?
     client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
     client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
If your app is successfully authenticated and the authorization code from the user is valid, the authorization server will return the access token:
In addition to the access token (the access_token parameter), the response contains the number of seconds until the token expires (the expires parameter). Once the token expires, you will need to re-run the steps above to generate a new code and access_token, although if the user has already authorized your app, they will not be prompted to do so again. If your app needs an access token with an infinite expiry time (perhaps to take actions on the user's behalf after they are not using your app), you can request the offline_access permission."