How do I implement secure OAuth2 consumption in Javascript?

前端 未结 2 1593
南方客
南方客 2020-12-07 08:37

I\'m in the process of designing an API in PHP that will use OAuth2.0. My end goal is to build a front-end application in javascript (using AngularJS) that accesses this API

相关标签:
2条回答
  • 2020-12-07 08:48

    The Implicit Grant flow (the one you're referring to as User-Agent Flow) is exactly the way to go:

    The implicit grant is a simplified authorization code flow optimized for clients implemented in a browser using a scripting language such as JavaScript.

    To understand the flow, the documentation from Google for client-side applications is a really good place to start. Note that they recommend you to take an additional token validation step to avoid confused deputy problems.

    Here is a short example implementation of the flow using the Soundcloud API and jQuery, taken from this answer:

    <script type="text/javascript" charset="utf-8">
      $(function () {
        var extractToken = function(hash) {
          var match = hash.match(/access_token=([\w-]+)/);
          return !!match && match[1];
        };
    
        var CLIENT_ID = YOUR_CLIENT_ID;
        var AUTHORIZATION_ENDPOINT = "https://soundcloud.com/connect";
        var RESOURCE_ENDPOINT = "https://api.soundcloud.com/me";
    
        var token = extractToken(document.location.hash);
        if (token) {
          $('div.authenticated').show();
    
          $('span.token').text(token);
    
          $.ajax({
              url: RESOURCE_ENDPOINT
            , beforeSend: function (xhr) {
                xhr.setRequestHeader('Authorization', "OAuth " + token);
                xhr.setRequestHeader('Accept',        "application/json");
              }
            , success: function (response) {
                var container = $('span.user');
                if (response) {
                  container.text(response.username);
                } else {
                  container.text("An error occurred.");
                }
              }
          });
        } else {
          $('div.authenticate').show();
    
          var authUrl = AUTHORIZATION_ENDPOINT + 
            "?response_type=token" +
            "&client_id="    + clientId +
            "&redirect_uri=" + window.location;
    
          $("a.connect").attr("href", authUrl);
        }
      });
    </script>
    <style>
      .hidden {
        display: none;
      }
    </style>
    
    <div class="authenticate hidden">
      <a class="connect" href="">Connect</a>
    </div>
    
    <div class="authenticated hidden">
      <p>
        You are using token
        <span class="token">[no token]</span>.
      </p>
    
      <p>
        Your SoundCloud username is
        <span class="user">[no username]</span>.
      </p>
    </div>
    

    For sending XMLHttpRequests (what the ajax() function does in jQuery) using AngularJS, refer to their documentation of the $http service.

    If you want to preserve state, when sending the user to the authorization endpoint, check out the state parameter.

    0 讨论(0)
  • 2020-12-07 08:56

    There's an example of Authorization Code Grant approach to get a token from OAuth server. I used jQuery ($) to make some operations.

    First, redirect user to authorization page.

    var authServerUri = "http://your-aouth2-server.com/authorize",
    authParams = {
      response_type: "code",
      client_id: this.model.get("clientId"),
      redirect_uri: this.model.get("redirectUri"),
      scope: this.model.get("scope"),
      state: this.model.get("state")
    };
    
    // Redirect to Authorization page.
    var replacementUri = authServerUri + "?" + $.param(authParams);
    window.location.replace(replacementUri);
    

    When one gave authorization pass to get token:

    var searchQueryString = window.location.search;
    if ( searchQueryString.charAt(0) === "?") {
      searchQueryString = searchQueryString.substring(1);
    }
    var searchParameters = $.deparam.fragment(searchQueryString);
    
    if ( "code" in searchParameters) {
      // TODO: construct a call like in previous step using $.ajax() to get token.
    }
    

    You could implement the Resource Owner Password Credentials Grant in the same manner using jQuery or pure XMLHttpRequest and don't make any redirects - because on each redirect you'll loose state of your application.

    For me, I used HTML5 local storage to persist state of my application for data which were not likely to pose a security threat.

    0 讨论(0)
提交回复
热议问题