Unverified Commit 239a7061 authored by Linus Lewandowski's avatar Linus Lewandowski Committed by Daniel Stenberg
Browse files

httpauth: add support for Bearer tokens

Closes #2102
parent 49fe65cc
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -56,6 +56,10 @@ defined in RFC2617 and is a more secure way to do authentication over public
networks than the regular old-fashioned Basic method. The IE flavor is simply
that libcurl will use a special "quirk" that IE is known to have used before
version 7 and that some servers require the client to use.
.IP CURLAUTH_BEARER
HTTP Bearer token authentication, used primarily in OAuth 2.0 protocol.

You can set the Bearer token to use with \fICURLOPT_XOAUTH2_BEARER(3)\fP.
.IP CURLAUTH_NEGOTIATE
HTTP Negotiate (SPNEGO) authentication. Negotiate authentication is defined
in RFC 4559 and is the most secure way to perform authentication over HTTP.
+4 −4
Original line number Diff line number Diff line
@@ -29,11 +29,11 @@ CURLOPT_XOAUTH2_BEARER \- specify OAuth 2.0 access token
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
.SH DESCRIPTION
Pass a char * as parameter, which should point to the zero terminated OAuth
2.0 Bearer Access Token for use with IMAP, POP3 and SMTP servers that support
the OAuth 2.0 Authorization Framework.
2.0 Bearer Access Token for use with HTTP, IMAP, POP3 and SMTP servers
that support the OAuth 2.0 Authorization Framework.

Note: The user name used to generate the Bearer Token should be supplied via
the \fICURLOPT_USERNAME(3)\fP option.
Note: For IMAP, POP3 and SMTP, the user name used to generate the Bearer Token
should be supplied via the \fICURLOPT_USERNAME(3)\fP option.

The application does not have to keep the string around after setting this
option.
+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
CURLAUTH_ANY                    7.10.6
CURLAUTH_ANYSAFE                7.10.6
CURLAUTH_BASIC                  7.10.6
CURLAUTH_BEARER                 7.61.0
CURLAUTH_DIGEST                 7.10.6
CURLAUTH_DIGEST_IE              7.19.3
CURLAUTH_GSSAPI                 7.55.0
+2 −0
Original line number Diff line number Diff line
@@ -691,6 +691,7 @@ typedef enum {
 * CURLAUTH_NTLM         - HTTP NTLM authentication
 * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour
 * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper
 * CURLAUTH_BEARER       - HTTP Bearer token authentication
 * CURLAUTH_ONLY         - Use together with a single other type to force no
 *                         authentication or just that single type
 * CURLAUTH_ANY          - All fine types set
@@ -708,6 +709,7 @@ typedef enum {
#define CURLAUTH_NTLM         (((unsigned long)1)<<3)
#define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5)
#define CURLAUTH_BEARER       (((unsigned long)1)<<6)
#define CURLAUTH_ONLY         (((unsigned long)1)<<31)
#define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+54 −1
Original line number Diff line number Diff line
@@ -310,6 +310,31 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
  return result;
}

/*
 * http_output_bearer() sets up an Authorization: header
 * for HTTP Bearer authentication.
 *
 * Returns CURLcode.
 */
static CURLcode http_output_bearer(struct connectdata *conn)
{
  char **userp;
  CURLcode result = CURLE_OK;

  userp = &conn->allocptr.userpwd;
  free(*userp);
  *userp = aprintf("Authorization: Bearer %s\r\n",
                   conn->oauth_bearer);

  if(!*userp) {
    result = CURLE_OUT_OF_MEMORY;
    goto fail;
  }

  fail:
  return result;
}

/* pickoneauth() selects the most favourable authentication method from the
 * ones available and the ones we want.
 *
@@ -326,6 +351,8 @@ static bool pickoneauth(struct auth *pick)
     of preference in case of the existence of multiple accepted types. */
  if(avail & CURLAUTH_NEGOTIATE)
    pick->picked = CURLAUTH_NEGOTIATE;
  else if(avail & CURLAUTH_BEARER)
    pick->picked = CURLAUTH_BEARER;
  else if(avail & CURLAUTH_DIGEST)
    pick->picked = CURLAUTH_DIGEST;
  else if(avail & CURLAUTH_NTLM)
@@ -628,6 +655,20 @@ output_auth_headers(struct connectdata *conn,
       functions work that way */
    authstatus->done = TRUE;
  }
  if(authstatus->picked == CURLAUTH_BEARER) {
    /* Bearer */
    if((!proxy && conn->oauth_bearer &&
        !Curl_checkheaders(conn, "Authorization:"))) {
      auth = "Bearer";
      result = http_output_bearer(conn);
      if(result)
        return result;
    }

    /* NOTE: this function should set 'done' TRUE, as the other auth
       functions work that way */
    authstatus->done = TRUE;
  }

  if(auth) {
    infof(data, "%s auth using %s with user '%s'\n",
@@ -674,7 +715,7 @@ Curl_http_output_auth(struct connectdata *conn,
  authproxy = &data->state.authproxy;

  if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
     conn->bits.user_passwd)
     conn->bits.user_passwd || conn->oauth_bearer)
    /* continue please */;
  else {
    authhost->done = TRUE;
@@ -883,6 +924,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
              data->state.authproblem = TRUE;
            }
          }
          else
            if(checkprefix("Bearer", auth)) {
              *availp |= CURLAUTH_BEARER;
              authp->avail |= CURLAUTH_BEARER;
              if(authp->picked == CURLAUTH_BEARER) {
                /* We asked for Bearer authentication but got a 40X back
                  anyway, which basically means our token isn't valid. */
                authp->avail = CURLAUTH_NONE;
                infof(data, "Authentication problem. Ignoring this.\n");
                data->state.authproblem = TRUE;
              }
            }

    /* there may be multiple methods on one line, so keep reading */
    while(*auth && *auth != ',') /* read up to the next comma */
Loading