$30 off During Our Annual Pro Sale. View Details »

Mastering OAuth 2.0 (True North PHP 2016)

Mastering OAuth 2.0 (True North PHP 2016)

OAuth 2.0 isn't easy, and everyone has a slightly different implementation, making interoperability a nightmare. Fortunately, the PHP League of Extraordinary Packages provides league/oauth2-client. Aiming for simplicity and ease-of-use, league/oauth2-client provides a common way to access providers. This talk introduces OAuth concepts, demonstrates how to perform OAuth flows with league/oauth2-client, and shows how to use league/oauth2-client to build a client library for your own provider.

Ben Ramsey
PRO

November 05, 2016
Tweet

More Decks by Ben Ramsey

Other Decks in Programming

Transcript

  1. Mastering
    OAuth 2.0
    Ben Ramsey

    True North PHP

    5 Nov 2016

    View Slide

  2. OAuth 2.0

    View Slide

  3. View Slide

  4. View Slide

  5. #1 Click to authorize

    View Slide

  6. #2 Log in on site and
    grant permission

    View Slide

  7. #3 Redirect back
    with auth code
    #4 Exchange code

    for access token

    View Slide

  8. #5 Use access token
    to get data

    View Slide

  9. bram.se/tnphp16-oauth2-app

    View Slide

  10. Preparing
    for OAuth

    View Slide

  11. 1. Register your application with the service
    2. Let the service know your domains or

    redirect URLs
    3. Configure your application to use the

    client ID and client secret given to you by

    the service
    ! No two OAuth 2.0
    providers are alike!

    View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. Integrating
    with the
    Provider

    View Slide

  18. composer require league/oauth2-instagram

    View Slide

  19. use League\OAuth2\Client\Provider\Instagram;
    $provider = new Instagram([
    'clientId' => 'CLIENT_ID',
    'clientSecret' => 'CLIENT_SECRET',
    'redirectUri' => 'https://example.com/redirect',
    ]);

    View Slide

  20. Authorization Request
    1. Generate authorization URL

    2. Store state to session

    3. Prompt user to authorize or redirect them

    View Slide

  21. $authUrl = $provider->getAuthorizationUrl();
    $request->session()->put(
    'instagramState',
    $provider->getState()
    );
    return redirect()->away($authUrl);

    View Slide

  22. Redirection Endpoint
    1. Receive authorization code

    2. Check state

    3. Exchange code for an access token

    View Slide

  23. $state = $request->session()->get('instagramState');
    if ($request->state !== $state) {
    abort(400, 'Invalid state');
    }
    if (!$request->has('code')) {
    abort(400, 'Authorization code not available');
    }
    $token = $provider->getAccessToken(
    'authorization_code',
    [
    'code' => $request->code,
    ]
    );
    $request->session()->put('instagramToken', $token);
    return redirect()->action('HomeController@index');

    View Slide

  24. Expiring & Refreshing Tokens
    1. Check for expiration & refresh token

    2. Request access token using refresh token

    View Slide

  25. if ($token->hasExpired() && $token->getRefreshToken()) {
    $newToken = $provider->getAccessToken('refresh_token', [
    'refresh_token' => $token->getRefreshToken(),
    );
    }
    $request->session()->put('accessToken', $token);
    ! Instagram does not
    support refresh tokens

    View Slide

  26. Using Access Tokens
    1. getAuthenticatedRequest() returns a PSR-7
    RequestInterface object

    2. Use your favorite HTTP request library to
    make a request

    View Slide

  27. $feedRequest = $provider->getAuthenticatedRequest(
    'GET',
    'https://api.instagram.com/v1/users/self/media/recent',
    $instagramToken
    );
    $client = new \GuzzleHttp\Client();
    $feedResponse = $client->send($feedRequest);
    $instagramFeed = json_decode(
    $feedResponse->getBody()->getContents()
    );

    View Slide

  28. A Brief
    History of Web
    Authorization

    View Slide

  29. What is
    OAuth 2.0?

    View Slide

  30. “However, as a rich and highly extensible
    framework with many optional components,
    on its own, this specification is likely to
    produce a wide range of non-interoperable
    implementations.”
    RFC 6749, Section 1.8

    View Slide

  31. 1. Resource owner

    2. Resource server

    3. Client

    4. Authorization server

    View Slide

  32. composer require league/oauth2-client

    View Slide

  33. use League\OAuth2\Client\Provider\GenericProvider;
    $provider = new GenericProvider([
    'clientId' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'clientSecret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'redirectUri' => 'https://you.example.com/redirect-url',
    'urlAuthorize' => 'https://them.example.net/authorize',
    'urlAccessToken' => 'https://them.example.net/token',
    'urlResourceOwnerDetails' =>
    'https://them.example.net/api/me'
    ]);

    View Slide

  34. Authorization Code
    1. Commonly referred to as three-legged

    2. Used in our Instagram example

    3. Very common grant type

    View Slide

  35. Resource Owner
    Client
    Auth Server
    Resource Server

    View Slide

  36. Step 1

    View Slide

  37. Step 2

    View Slide

  38. Step 3

    View Slide

  39. Step 4

    View Slide

  40. 1. Gives username and password to client

    2. Client exchanges them for access token

    3. Use with extreme caution
    Resource Owner Password
    Credentials

    View Slide

  41. Resource Owner
    Client
    Auth Server Resource Server

    View Slide

  42. Step 1

    View Slide

  43. Step 2

    View Slide

  44. Step 3

    View Slide

  45. $accessToken = $provider->getAccessToken('password', [
    'username' => 'demouser',
    'password' => 'testpass'
    ]);

    View Slide

  46. Client Credentials
    1. Client is the resource owner

    2. Credentials are stored in the client (usually
    safely on the server)

    View Slide

  47. Client
    Auth Server Resource Server

    View Slide

  48. Step 1

    View Slide

  49. Step 2

    View Slide

  50. $accessToken = $provider->getAccessToken(
    'client_credentials'
    );

    View Slide

  51. Implicit
    1. Relies on client-side redirection using a
    client ID and a known redirection URL

    2. league/oauth2-client cannot support this

    View Slide

  52. Toward a
    More Secure Web

    View Slide

  53. THANK YOU.
    ANY QUESTIONS?
    If you want to talk more, feel
    free to contact me.
    benramsey.com
    @ramsey
    github.com/ramsey
    [email protected]
    Mastering OAuth 2.0

    Copyright © 2016 Ben Ramsey

    This work is licensed under Creative Commons
    Attribution-ShareAlike 4.0 International. For uses not
    covered under this license, please contact the author.
    Ramsey, Ben. “Mastering OAuth 2.0.” True North PHP. Microsoft
    Canada, Mississauga. 5 Nov. 2016. Conference presentation.
    This presentation was created using Keynote. The text
    is set in Chunk Five, Helvetica Neue, and Marker Felt.
    The source code is set in Menlo. The iconography is
    provided by Font Awesome.

    Unless otherwise noted, all photographs are used by
    permission under a Creative Commons license. Please
    refer to the Photo Credits slide for more information.
    Ŏ joind.in/talk/7a6db

    View Slide

  54. Photo Credits
    1. “Untitled” by MICⱵ^ΞL
    2. “Master” by Giuditta
    3. “Untitled” by MICⱵ^ΞL
    4. “Untitled” by MICⱵ^ΞL
    5. “Untitled” by MICⱵ^ΞL
    6. “master gain” by Chris Blakeley
    7. “Mixing board” by Kevin Jaako
    1 2
    3 4
    5 6
    7

    View Slide