Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS & node.js: how to verify passed access token?

Tags:

I have an iOS which uses OAuth and OAuth2 providers (Facebook, google, twitter, etc) to validate a user and provide access tokens. Apart from minimal data such as name and email address, the app doesn't uses these services for anything except authentication.

The app then sends the access token to a server to indicate that the user is authenticated.

The server is written in Node.js and before doing anything it needs to validate the supplied access token against the correct OAuth* service.

I've been looking around, but so far all the node.js authentication modules I've found appear to be for logging in and authenticating through web pages supplied by the server.

Does anyone know any node.js modules that can do simple validation of a supplied access token?

like image 360
drekka Avatar asked Aug 10 '12 02:08

drekka


People also ask

What is iOS stand for?

2 iOS, an acronym for iPhone Operating System, is a Unix-derived operating system powering all of Apple's mobile devices. 3 The name iOS was not officially applied to the software until 2008, when Apple released the iPhone software development kit (SDK), enabling any app makers to create applications for the platform.

Which is the current iOS version?

The latest version of iOS and iPadOS is 15.6. 1. Learn how to update the software on your iPhone, iPad, or iPod touch. The latest version of macOS is 12.5.

Does iPhone 11 have iOS 16?

That means it will be available for the following devices: iPhone SE, iPhone 8 and iPhone 8 Plus, iPhone X, iPhone XR, iPhone 11, iPhone 11 Pro, iPhone 11 Pro Max, iPhone 12 mini, iPhone 12, iPhone 12 Pro, iPhone 12 Pro Max, iPhone 13 mini, iPhone 13, iPhone 13 Pro and the iPhone 13 Pro Max.


2 Answers

To the best of my knowledge (and as far as I can tell from reading the specifications) the OAuth and OAuth 2 specs do not specify a single endpoint for access token validation. That means you will need custom code for each of the providers to validate an access token only.

I looked up what to do for the endpoints you specified:

Facebook

It seems others have used the graph API's 'me' endpoint for Facebook to check if the token is valid. Basically, request:

https://graph.facebook.com/me?access_token={accessToken} 

Google

Google have a dedicated debugging endpoint for getting access token information, with nice documentation, too. Basically, request:

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={accessToken} 

However, they recommend that you don't do this for production:

The tokeninfo endpoint is useful for debugging but for production purposes, retrieve Google's public keys from the keys endpoint and perform the validation locally. You should retrieve the keys URI from the Discovery document using the jwks_uri metadata value. Requests to the debugging endpoint may be throttled or otherwise subject to intermittent errors.

Since Google changes its public keys only infrequently, you can cache them using the cache directives of the HTTP response and, in the vast majority of cases, perform local validation much more efficiently than by using the tokeninfo endpoint. This validation requires retrieving and parsing certificates, and making the appropriate cryptographic calls to check the signature. Fortunately, there are well-debugged libraries available in a wide variety of languages to accomplish this (see jwt.io).

Twitter

Twitter doesn't seem to have a really obvious way to do this. I would suspect that because the account settings data is pretty static, that might be the best way of verifying (fetching tweets would presumably have a higher latency?), so you can request (with the appropriate OAuth signature etc.):

https://api.twitter.com/1.1/account/settings.json 

Note that this API is rate-limited to 15 times per window.

All in all this seems trickier than it would first appear. It might be a better idea to implement some kind of session/auth support on the server. Basically, you could verify the external OAuth token you get once, and then assign the user some session token of your own with which you authenticate with the user ID (email, FB id, whatever) on your own server, rather than continuing to make requests to the OAuth providers for every request you get yourself.

Hope that helps!

like image 137
Gijs Avatar answered Sep 25 '22 18:09

Gijs


For google in production, install google-auth-library (npm install google-auth-library --save) and use the following:

const { OAuth2Client } = require('google-auth-library'); const client = new OAuth2Client(GOOGLE_CLIENT_ID); // Replace by your client ID  async function verifyGoogleToken(token) {   const ticket = await client.verifyIdToken({     idToken: token,     audience: GOOGLE_CLIENT_ID  // Replace by your client ID    });   const payload = ticket.getPayload();   return payload; }  router.post("/auth/google", (req, res, next) => {   verifyGoogleToken(req.body.idToken).then(user => {     console.log(user); // Token is valid, do whatever you want with the user    })   .catch(console.error); // Token invalid }); 

More info on Authenticate google token with a backend server, examples for node.js, java, python and php can be found.

For Facebook, do an https request like:

const https = require('https');  router.post("/auth/facebook", (req, res, next) => {    const options = {     hostname: 'graph.facebook.com',     port: 443,     path: '/me?access_token=' + req.body.authToken,     method: 'GET'   }    const request = https.get(options, response => {     response.on('data', function (user) {       user = JSON.parse(user.toString());       console.log(user);     });   })    request.on('error', (message) => {     console.error(message);   });    request.end(); }) 
like image 28
Kurt Van den Branden Avatar answered Sep 25 '22 18:09

Kurt Van den Branden