integrating oauth and social login into wordpress

33
INTEGRATING OAUTH AND SOCIAL LOGIN INTO WORDPRESS William Tam, WNET/Thirteen

Upload: william-tam

Post on 22-Mar-2017

98 views

Category:

Internet


1 download

TRANSCRIPT

Page 1: Integrating OAuth and Social Login Into Wordpress

INTEGRATING OAUTH AND

SOCIAL LOGIN INTO WORDPRESS

William Tam, WNET/Thirteen

Page 2: Integrating OAuth and Social Login Into Wordpress

Who am I?• Built my first web page in 1993, and have been doing so ever

since, mostly for non-profit orgs. I work for WNET/Thirteen now and freelance a little

• First touched WordPress in 2012 while freelancing• Playing with OAuth since 2013 when I built a YouTube upload/edit

system for the PBS NewsHour website.

Page 3: Integrating OAuth and Social Login Into Wordpress

What is ‘Social Login’?• Social login is NOT social sharing. If you just need social sharing,

AddThis is excellent!• If you’re just looking for a good plugin and want to skip the details,

the ‘WordPress Social Login’ plugin seems to be a good choice.• If you want to understand how it all works, stick around to hear

about OAuth!

Page 4: Integrating OAuth and Social Login Into Wordpress

What do we mean by OAuth? • OAuth is a way for users to approve an app or website to have access to

a resource without sharing their passwords with the app/website• OAuth (1) (originally 'Twitter OAuth‘) Uses digital signatures which can be

hard to implement. Few providers other than Twitter still suppport it• OAuth2 uses SSL instead of signatures. Flexible (perhaps too flexible) to

implement, easy to implement insecurely! Very little standardization• OpenID Connect (OIDC) is a specification that uses OAuth2 with

standardized secure implementation details, particularly the ‘id_token’, that make it much harder to mess up. Google, Yahoo, Microsoft, Amazon, and some others support it, but Facebook doesn’t support OIDC (yet)

Page 5: Integrating OAuth and Social Login Into Wordpress

HOW DOES OAUTH WORK?

Page 6: Integrating OAuth and Social Login Into Wordpress

OAuth in a nutshell• User visits your website, clicks on a link that sends them to a

provider like Google or Facebook where you've registered some configuration details in advance.

• If the details you registered match the arguments in the query string of that link, AND the user logs in to that provider, the user is redirected back to a special URL on your website

• Your website uses data it reads from that special URL to get an access token

• Your website can then use that token to get access to stuff on the provider

Page 7: Integrating OAuth and Social Login Into Wordpress

Step 1: Register an ‘app’ to store config• Developer or site admin registers an 'app' with an identity provider

such as Google, Facebook, Yahoo, or the like • Google Developer Console: https://console.developers.google.com/• Facebook for Developers: https://developers.facebook.com• All of the ID providers have some sort of console

Page 8: Integrating OAuth and Social Login Into Wordpress

Configuring the ‘app’• Allowed Origin Domain(s)• Allowed Redirect URI(s)• Scope(s)

Page 9: Integrating OAuth and Social Login Into Wordpress

Configuring the ‘app’• Consent screen• Identity provider assigns and returns a client id and secret for that

specific ‘app’.

Page 10: Integrating OAuth and Social Login Into Wordpress
Page 11: Integrating OAuth and Social Login Into Wordpress

Step 2: Get your token(s)There are two “flows” for OAuth to get an access token. • Implicit Flow:

• Client-only, can be done with only HTML and JS, easy to code• Not very secure • Authorization expires when the access token expires – typically 1 hour

• Code Exchange Flow:• Requires server coding, much more complex• More secure, uses server-to-server communication• Enables long-term/offline authorization using refresh tokens

Page 12: Integrating OAuth and Social Login Into Wordpress

Tokens are just stringsImplicit flow puts it as a ‘fragment’ appended to the Redirect URI:https://somesite.com/oauthcallback#access_token=1/fFBGRNJru1FQd44AzqT3Zg&token_type=Bearer&expires_in=3600&nonce=DgkRrHXmyu3KLd0KDdfq

Authorization code flow returns JSON (usually):{ "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", "expires_in":3920, "token_type":"Bearer", "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"}

Page 13: Integrating OAuth and Social Login Into Wordpress

Implicit flow

Page 14: Integrating OAuth and Social Login Into Wordpress

Example: Get Google OAuth Token function requestGoogleOAuthToken() { var popupurl = 'https://accounts.google.com/o/oauth2/auth?scope=profile email openid&client_id=' + CLIENT_ID + '&redirect_uri=' + REDIRECT_URI + '&response_type=token'; var win = window.open(popupurl, "googleauthwindow", 'width=800, height=600'); var pollTimer = window.setInterval(function() { try { if (win.document.URL.indexOf(REDIRECT_URI) != -1) { window.clearInterval(pollTimer); google_access_token = win.document.URL.match( /access_token=(.*)\&/); win.close(); getGoogleUserInfo(google_access_token[1]); } } catch(e) {} }, 500); }

Page 15: Integrating OAuth and Social Login Into Wordpress

Example: Get Google OAuth Token function requestGoogleOAuthToken() { var popupurl = 'https://accounts.google.com/o/oauth2/auth?scope=profile email openid&client_id=' + CLIENT_ID + '&redirect_uri=' + REDIRECT_URI + '&response_type=token'; var win = window.open(popupurl, "googleauthwindow", 'width=800, height=600'); var pollTimer = window.setInterval(function() { try { if (win.document.URL.indexOf(REDIRECT_URI) != -1) { window.clearInterval(pollTimer); google_access_token = win.document.URL.match( /access_token=(.*)\&/); win.close(); validateGoogleAccessToken(google_access_token[1]); } } catch(e) {} }, 500); }

Page 16: Integrating OAuth and Social Login Into Wordpress

Example: Validate Access Tokenfunction validateGoogleAccessToken(GoogleAccessToken) { $.ajax({ url: 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + GoogleAccessToken, data: null, dataType: "jsonp", success: function(responseText){ if (responseText.error || responseText.audience !== CLIENT_ID) { console.log(responseText); } else { getGoogleUserInfo(GoogleAccessToken); } } }); }

Page 17: Integrating OAuth and Social Login Into Wordpress

Example: Get Google UserInfo function getGoogleUserInfo(google_access_token) { $.ajax({ url: 'https://www.googleapis.com/plus/v1/people/me/openIdConnect', data: { access_token: google_access_token }, success: function(user) { $('#googleUserName').text('You are logged in as ' + user.name); }, dataType: "jsonp" }); }

Page 18: Integrating OAuth and Social Login Into Wordpress

Security checklist• Validate the access token against the tokeninfo endpoint• The state parameter – whatever you put into it you should get

back unchanged. This can be a nonce, or encrypted hash, which leads us to…

• JSON Web Tokens – the standard for representing ‘claims’. https://jwt.io/ for more info

• Limit the scopes – least privilege principle

Page 19: Integrating OAuth and Social Login Into Wordpress

Authorization code flow

Page 20: Integrating OAuth and Social Login Into Wordpress

The Refresh Token is MAGIC!• Refresh token doesn’t give access to resources, just new access tokens• Refresh token is used to get (a) new access token. It requires the client id and

client secret to retrieve• The user does not need to be present• The refresh token never (or rarely) expires on its own – some expire after 2

weeks, or a year. Google’s refresh tokens never expire• Some OAuth implementations allow multiple use refresh tokens, others expire

them immediately. Others rate-limit the number of access tokens provided• Changing account passwords do not invalidate a refresh token• Revoking refresh tokens is different for different identity providers. Provide

means to do so!

Page 21: Integrating OAuth and Social Login Into Wordpress

Example: Get/Update OAuth Tokenfunction set_google_oauth2_token($grantCode, $grantType) { $settings = get_option('foo_oauth_demo_settings', true); $clienttoken_post = array( "client_id" => $settings['google_app_client_id'],"client_secret" => $settings['google_app_client_secret'] ); if ($grantType === "auth_code"){ $clienttoken_post["code"] = $grantCode; $clienttoken_post["redirect_uri"] = $settings['google_app_redirect_uri']; $clienttoken_post["grant_type"] = "authorization_code"; } if ($grantType === "refresh_token"){ $clienttoken_post["refresh_token"] = get_option('foo_google_refresh_token', true); $clienttoken_post["grant_type"] = "refresh_token"; } $postargs = array( 'body' => $clienttoken_post ); $response = wp_remote_post(‘https://accounts.google.com/o/oauth2/token’, $postargs );

Page 22: Integrating OAuth and Social Login Into Wordpress

Example: Get/Update OAuth Tokenfunction set_google_oauth2_token($grantCode, $grantType) { $settings = get_option('foo_oauth_demo_settings', true); $clienttoken_post = array( "client_id" => $settings['google_app_client_id'],"client_secret" => $settings['google_app_client_secret'] ); if ($grantType === "auth_code"){ $clienttoken_post["code"] = $grantCode; $clienttoken_post["redirect_uri"] = $settings['google_app_redirect_uri']; $clienttoken_post["grant_type"] = "authorization_code"; } if ($grantType === "refresh_token"){ $clienttoken_post["refresh_token"] = get_option('foo_google_refresh_token', true); $clienttoken_post["grant_type"] = "refresh_token"; } $postargs = array( 'body' => $clienttoken_post ); $response = wp_remote_post(‘https://accounts.google.com/o/oauth2/token’, $postargs );

Page 23: Integrating OAuth and Social Login Into Wordpress

Example: Get/Update OAuth Tokenfunction set_google_oauth2_token($grantCode, $grantType) { $settings = get_option('foo_oauth_demo_settings', true); $clienttoken_post = array( "client_id" => $settings['google_app_client_id'],"client_secret" => $settings['google_app_client_secret'] ); if ($grantType === "auth_code"){ $clienttoken_post["code"] = $grantCode; $clienttoken_post["redirect_uri"] = $settings['google_app_redirect_uri']; $clienttoken_post["grant_type"] = "authorization_code"; } if ($grantType === "refresh_token"){ $clienttoken_post["refresh_token"] = get_option('foo_google_refresh_token', true); $clienttoken_post["grant_type"] = "refresh_token"; } $postargs = array( 'body' => $clienttoken_post ); $response = wp_remote_post(‘https://accounts.google.com/o/oauth2/token’, $postargs );

Page 24: Integrating OAuth and Social Login Into Wordpress

Example: Get/Update OAuth Token (cnt’d) $authObj = json_decode(wp_remote_retrieve_body( $response ), true); if (isset($authObj[refresh_token])){ $refreshToken = $authObj[refresh_token]; $success = update_option('foo_google_refresh_token', $refreshToken, false); } if ($success) { $success = update_option('foo_google_access_token_expires', strtotime("+" . $authObj[expires_in] . " seconds")); } if ($success) { $success = update_option('foo_google_access_token', $authObj[access_token], false); if ($success) { $success = $authObj[access_token]; } } if (!$success) { $success=false; } return $success; }

Page 25: Integrating OAuth and Social Login Into Wordpress

Example: Get/Update OAuth Token (pt3)function get_google_access_token() { $expiration_time = get_option('foo_google_access_token_expires', true); if (! $expiration_time) { return false; } // Give the access token a 5 minute buffer (300 seconds) $expiration_time = $expiration_time - 300; if (time() < $expiration_time) { return get_option('foo_google_access_token', true); } // at this point we have an expiration time but it is in the past or will be very soon return $this->set_google_oauth2_token(null, 'refresh_token'); }

Page 26: Integrating OAuth and Social Login Into Wordpress

SOCIAL LOGIN

Page 27: Integrating OAuth and Social Login Into Wordpress

The ‘Create WordPress User’ approach• Integrates with WordPress internals• Negates most caching • Use a plugin! This stuff is hard and it is easy to get wrong• I recommend the ‘WordPress Social Login’ plugin

• open source• well supported • excellent integration capacity• I am not connected with it!

• https://wordpress.org/plugins/wordpress-social-login/

Page 28: Integrating OAuth and Social Login Into Wordpress
Page 29: Integrating OAuth and Social Login Into Wordpress
Page 30: Integrating OAuth and Social Login Into Wordpress

The ‘Client-only’, ‘no WP users’ approach• I have over 100k members who could be logging in. I can’t create/maintain that

many WP user accounts, can’t afford all of those database hits, must have caching • I only need to provide access to external APIs/resources• I do login etc in JavaScript in the browser, store the tokens and userinfo in cookies• I use the authorization code flow• Endpoints built into my plugin:

• Oauthcallback endpoint for initial login and then cookie setting• Each pageview triggers a JavaScript/Ajax call to the Authentication endpoint, reads/sets

cookies• Tokens are in encrypted cookies. Encryption is easy….to get WRONG• No critical user data is exposed to JavaScript

Page 31: Integrating OAuth and Social Login Into Wordpress
Page 32: Integrating OAuth and Social Login Into Wordpress

Resources• These slides have notes -- http://tinyurl.com/tamw-oauthpreso• I blog at ieg.wnet.org/author/tamw with detailed posts AND

SOURCE CODE • Google’s developer documentation is an excellent guide to OAuth -

https://developers.google.com/identity/protocols/OAuth2• JSON Web Tokens - https://jwt.io/• InfoSec StackExchange - http://security.stackexchange.com/

Page 33: Integrating OAuth and Social Login Into Wordpress

QUESTIONS?