Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HMAC_SHA256 to client auth #692

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion authlib/integrations/httpx_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from authlib.oauth1 import (
SIGNATURE_HMAC_SHA1,
SIGNATURE_HMAC_SHA256,
SIGNATURE_RSA_SHA1,
SIGNATURE_PLAINTEXT,
SIGNATURE_TYPE_HEADER,
Expand All @@ -18,7 +19,7 @@
__all__ = [
'OAuthError',
'OAuth1Auth', 'AsyncOAuth1Client',
'SIGNATURE_HMAC_SHA1', 'SIGNATURE_RSA_SHA1', 'SIGNATURE_PLAINTEXT',
'SIGNATURE_HMAC_SHA1', 'SIGNATURE_HMAC_SHA256', 'SIGNATURE_RSA_SHA1', 'SIGNATURE_PLAINTEXT',
'SIGNATURE_TYPE_HEADER', 'SIGNATURE_TYPE_QUERY', 'SIGNATURE_TYPE_BODY',
'OAuth2Auth', 'OAuth2ClientAuth', 'OAuth2Client', 'AsyncOAuth2Client',
'AssertionClient', 'AsyncAssertionClient',
Expand Down
3 changes: 2 additions & 1 deletion authlib/integrations/requests_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ..base_client import OAuthError
from authlib.oauth1 import (
SIGNATURE_HMAC_SHA1,
SIGNATURE_HMAC_SHA256,
SIGNATURE_RSA_SHA1,
SIGNATURE_PLAINTEXT,
SIGNATURE_TYPE_HEADER,
Expand All @@ -15,7 +16,7 @@
__all__ = [
'OAuthError',
'OAuth1Session', 'OAuth1Auth',
'SIGNATURE_HMAC_SHA1', 'SIGNATURE_RSA_SHA1', 'SIGNATURE_PLAINTEXT',
'SIGNATURE_HMAC_SHA1', 'SIGNATURE_HMAC_SHA256', 'SIGNATURE_RSA_SHA1', 'SIGNATURE_PLAINTEXT',
'SIGNATURE_TYPE_HEADER', 'SIGNATURE_TYPE_QUERY', 'SIGNATURE_TYPE_BODY',
'OAuth2Session', 'OAuth2Auth',
'AssertionSession',
Expand Down
2 changes: 2 additions & 0 deletions authlib/oauth1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
OAuth1Request,
ClientAuth,
SIGNATURE_HMAC_SHA1,
SIGNATURE_HMAC_SHA256,
SIGNATURE_RSA_SHA1,
SIGNATURE_PLAINTEXT,
SIGNATURE_TYPE_HEADER,
Expand All @@ -19,6 +20,7 @@
'OAuth1Request',
'ClientAuth',
'SIGNATURE_HMAC_SHA1',
'SIGNATURE_HMAC_SHA256',
'SIGNATURE_RSA_SHA1',
'SIGNATURE_PLAINTEXT',
'SIGNATURE_TYPE_HEADER',
Expand Down
2 changes: 2 additions & 0 deletions authlib/oauth1/rfc5849/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .client_auth import ClientAuth
from .signature import (
SIGNATURE_HMAC_SHA1,
SIGNATURE_HMAC_SHA256,
SIGNATURE_RSA_SHA1,
SIGNATURE_PLAINTEXT,
SIGNATURE_TYPE_HEADER,
Expand All @@ -30,6 +31,7 @@
'OAuth1Request',
'ClientAuth',
'SIGNATURE_HMAC_SHA1',
'SIGNATURE_HMAC_SHA256',
'SIGNATURE_RSA_SHA1',
'SIGNATURE_PLAINTEXT',
'SIGNATURE_TYPE_HEADER',
Expand Down
3 changes: 3 additions & 0 deletions authlib/oauth1/rfc5849/client_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .wrapper import OAuth1Request
from .signature import (
SIGNATURE_HMAC_SHA1,
SIGNATURE_HMAC_SHA256,
SIGNATURE_PLAINTEXT,
SIGNATURE_RSA_SHA1,
SIGNATURE_TYPE_HEADER,
Expand All @@ -15,6 +16,7 @@
)
from .signature import (
sign_hmac_sha1,
sign_hmac_sha256,
sign_rsa_sha1,
sign_plaintext
)
Expand All @@ -32,6 +34,7 @@
class ClientAuth:
SIGNATURE_METHODS = {
SIGNATURE_HMAC_SHA1: sign_hmac_sha1,
SIGNATURE_HMAC_SHA256: sign_hmac_sha256,
SIGNATURE_RSA_SHA1: sign_rsa_sha1,
SIGNATURE_PLAINTEXT: sign_plaintext,
}
Expand Down
52 changes: 52 additions & 0 deletions authlib/oauth1/rfc5849/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .util import escape, unescape

SIGNATURE_HMAC_SHA1 = "HMAC-SHA1"
SIGNATURE_HMAC_SHA256 = "HMAC-SHA256"
SIGNATURE_RSA_SHA1 = "RSA-SHA1"
SIGNATURE_PLAINTEXT = "PLAINTEXT"

Expand Down Expand Up @@ -294,6 +295,50 @@ def hmac_sha1_signature(base_string, client_secret, token_secret):
return to_unicode(sig)


def hmac_sha256_signature(base_string, client_secret, token_secret):
"""Generate signature via HMAC-SHA256 method

The "HMAC-SHA256" signature method uses the HMAC-SHA256 signature
algorithm::

digest = HMAC-SHA256 (key, text)

"""

# The HMAC-SHA256 function variables are used in following way:

# text is set to the value of the signature base string from
# `Section 3.4.1.1`_.
#
# .. _`Section 3.4.1.1`: https://tools.ietf.org/html/rfc5849#section-3.4.1.1
text = base_string

# key is set to the concatenated values of:
# 1. The client shared-secret, after being encoded (`Section 3.6`_).
#
# .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6
key = escape(client_secret or '')

# 2. An "&" character (ASCII code 38), which MUST be included
# even when either secret is empty.
key += '&'

# 3. The token shared-secret, after being encoded (`Section 3.6`_).
#
# .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6
key += escape(token_secret or '')

signature = hmac.new(to_bytes(key), to_bytes(text), hashlib.sha256)

# digest is used to set the value of the "oauth_signature" protocol
# parameter, after the result octet string is base64-encoded
# per `RFC2045, Section 6.8`.
#
# .. _`RFC2045, Section 6.8`: https://tools.ietf.org/html/rfc2045#section-6.8
sig = binascii.b2a_base64(signature.digest())[:-1]
return to_unicode(sig)


def rsa_sha1_signature(base_string, rsa_private_key):
"""Generate signature via RSA-SHA1 method, per `Section 3.4.3`_.

Expand Down Expand Up @@ -353,6 +398,13 @@ def sign_hmac_sha1(client, request):
base_string, client.client_secret, client.token_secret)


def sign_hmac_sha256(client, request):
"""Sign a HMAC-SHA1 signature."""
base_string = generate_signature_base_string(request)
return hmac_sha256_signature(
base_string, client.client_secret, client.token_secret)


def sign_rsa_sha1(client, request):
"""Sign a RSASSA-PKCS #1 v1.5 base64 encoded signature."""
base_string = generate_signature_base_string(request)
Expand Down
Loading