1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-23 16:48:49 -05:00

httpauth: add support for Bearer tokens

Closes #2102
This commit is contained in:
Linus Lewandowski 2018-05-22 12:28:41 +02:00 committed by Daniel Stenberg
parent 49fe65ccd8
commit 239a7061f8
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
8 changed files with 124 additions and 5 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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))

View File

@ -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 */

View File

@ -601,6 +601,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
break;
case 'B': /* OAuth 2.0 bearer token */
GetStr(&config->oauth_bearer, nextarg);
config->authtype |= CURLAUTH_BEARER;
break;
case 'c': /* connect-timeout */
err = str2udouble(&config->connecttimeout, nextarg,

View File

@ -196,5 +196,6 @@ test2056 test2057 test2058 test2059 test2060 test2061 test2062 test2063 \
test2064 test2065 test2066 test2067 test2068 test2069 \
\
test2070 test2071 test2072 test2073 \
test2074 \
\
test3000 test3001

57
tests/data/test2074 Normal file
View File

@ -0,0 +1,57 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
AUTH OAUTHBEARER
</keywords>
</info>
#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
</reply>
#
# Client-side
<client>
<server>
http
</server>
<name>
HTTP GET
</name>
<command>
http://%HOSTIP:%HTTPPORT/2074 --oauth2-bearer mF_9.B5f-4.1JqM
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /2074 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Bearer mF_9.B5f-4.1JqM
Accept: */*
</protocol>
</verify>
</testcase>