mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-19 21:03:21 -07:00
Update oauthlib-3.1.1
This commit is contained in:
parent
e58aa40099
commit
d76838a607
64 changed files with 4329 additions and 1421 deletions
9
lib/oauthlib/openid/connect/core/endpoints/__init__.py
Normal file
9
lib/oauthlib/openid/connect/core/endpoints/__init__.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
"""
|
||||
oauthlib.oopenid.core
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module is an implementation of various logic needed
|
||||
for consuming and providing OpenID Connect
|
||||
"""
|
||||
from .pre_configured import Server
|
||||
from .userinfo import UserInfoEndpoint
|
97
lib/oauthlib/openid/connect/core/endpoints/pre_configured.py
Normal file
97
lib/oauthlib/openid/connect/core/endpoints/pre_configured.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
"""
|
||||
oauthlib.openid.connect.core.endpoints.pre_configured
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module is an implementation of various endpoints needed
|
||||
for providing OpenID Connect servers.
|
||||
"""
|
||||
from oauthlib.oauth2.rfc6749.endpoints import (
|
||||
AuthorizationEndpoint, IntrospectEndpoint, ResourceEndpoint,
|
||||
RevocationEndpoint, TokenEndpoint,
|
||||
)
|
||||
from oauthlib.oauth2.rfc6749.grant_types import (
|
||||
AuthorizationCodeGrant as OAuth2AuthorizationCodeGrant,
|
||||
ClientCredentialsGrant, ImplicitGrant as OAuth2ImplicitGrant,
|
||||
RefreshTokenGrant, ResourceOwnerPasswordCredentialsGrant,
|
||||
)
|
||||
from oauthlib.oauth2.rfc6749.tokens import BearerToken
|
||||
|
||||
from ..grant_types import AuthorizationCodeGrant, HybridGrant, ImplicitGrant
|
||||
from ..grant_types.dispatchers import (
|
||||
AuthorizationCodeGrantDispatcher, AuthorizationTokenGrantDispatcher,
|
||||
ImplicitTokenGrantDispatcher,
|
||||
)
|
||||
from ..tokens import JWTToken
|
||||
from .userinfo import UserInfoEndpoint
|
||||
|
||||
|
||||
class Server(AuthorizationEndpoint, IntrospectEndpoint, TokenEndpoint,
|
||||
ResourceEndpoint, RevocationEndpoint, UserInfoEndpoint):
|
||||
|
||||
"""An all-in-one endpoint featuring all four major grant types."""
|
||||
|
||||
def __init__(self, request_validator, token_expires_in=None,
|
||||
token_generator=None, refresh_token_generator=None,
|
||||
*args, **kwargs):
|
||||
"""Construct a new all-grants-in-one server.
|
||||
|
||||
:param request_validator: An implementation of
|
||||
oauthlib.oauth2.RequestValidator.
|
||||
:param token_expires_in: An int or a function to generate a token
|
||||
expiration offset (in seconds) given a
|
||||
oauthlib.common.Request object.
|
||||
:param token_generator: A function to generate a token from a request.
|
||||
:param refresh_token_generator: A function to generate a token from a
|
||||
request for the refresh token.
|
||||
:param kwargs: Extra parameters to pass to authorization-,
|
||||
token-, resource-, and revocation-endpoint constructors.
|
||||
"""
|
||||
self.auth_grant = OAuth2AuthorizationCodeGrant(request_validator)
|
||||
self.implicit_grant = OAuth2ImplicitGrant(request_validator)
|
||||
self.password_grant = ResourceOwnerPasswordCredentialsGrant(
|
||||
request_validator)
|
||||
self.credentials_grant = ClientCredentialsGrant(request_validator)
|
||||
self.refresh_grant = RefreshTokenGrant(request_validator)
|
||||
self.openid_connect_auth = AuthorizationCodeGrant(request_validator)
|
||||
self.openid_connect_implicit = ImplicitGrant(request_validator)
|
||||
self.openid_connect_hybrid = HybridGrant(request_validator)
|
||||
|
||||
self.bearer = BearerToken(request_validator, token_generator,
|
||||
token_expires_in, refresh_token_generator)
|
||||
|
||||
self.jwt = JWTToken(request_validator, token_generator,
|
||||
token_expires_in, refresh_token_generator)
|
||||
|
||||
self.auth_grant_choice = AuthorizationCodeGrantDispatcher(default_grant=self.auth_grant, oidc_grant=self.openid_connect_auth)
|
||||
self.implicit_grant_choice = ImplicitTokenGrantDispatcher(default_grant=self.implicit_grant, oidc_grant=self.openid_connect_implicit)
|
||||
|
||||
# See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Combinations for valid combinations
|
||||
# internally our AuthorizationEndpoint will ensure they can appear in any order for any valid combination
|
||||
AuthorizationEndpoint.__init__(self, default_response_type='code',
|
||||
response_types={
|
||||
'code': self.auth_grant_choice,
|
||||
'token': self.implicit_grant_choice,
|
||||
'id_token': self.openid_connect_implicit,
|
||||
'id_token token': self.openid_connect_implicit,
|
||||
'code token': self.openid_connect_hybrid,
|
||||
'code id_token': self.openid_connect_hybrid,
|
||||
'code id_token token': self.openid_connect_hybrid,
|
||||
'none': self.auth_grant
|
||||
},
|
||||
default_token_type=self.bearer)
|
||||
|
||||
self.token_grant_choice = AuthorizationTokenGrantDispatcher(request_validator, default_grant=self.auth_grant, oidc_grant=self.openid_connect_auth)
|
||||
|
||||
TokenEndpoint.__init__(self, default_grant_type='authorization_code',
|
||||
grant_types={
|
||||
'authorization_code': self.token_grant_choice,
|
||||
'password': self.password_grant,
|
||||
'client_credentials': self.credentials_grant,
|
||||
'refresh_token': self.refresh_grant,
|
||||
},
|
||||
default_token_type=self.bearer)
|
||||
ResourceEndpoint.__init__(self, default_token='Bearer',
|
||||
token_types={'Bearer': self.bearer, 'JWT': self.jwt})
|
||||
RevocationEndpoint.__init__(self, request_validator)
|
||||
IntrospectEndpoint.__init__(self, request_validator)
|
||||
UserInfoEndpoint.__init__(self, request_validator)
|
99
lib/oauthlib/openid/connect/core/endpoints/userinfo.py
Normal file
99
lib/oauthlib/openid/connect/core/endpoints/userinfo.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
"""
|
||||
oauthlib.openid.connect.core.endpoints.userinfo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module is an implementation of userinfo endpoint.
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
|
||||
from oauthlib.common import Request
|
||||
from oauthlib.oauth2.rfc6749 import errors
|
||||
from oauthlib.oauth2.rfc6749.endpoints.base import (
|
||||
BaseEndpoint, catch_errors_and_unavailability,
|
||||
)
|
||||
from oauthlib.oauth2.rfc6749.tokens import BearerToken
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserInfoEndpoint(BaseEndpoint):
|
||||
"""Authorizes access to userinfo resource.
|
||||
"""
|
||||
def __init__(self, request_validator):
|
||||
self.bearer = BearerToken(request_validator, None, None, None)
|
||||
self.request_validator = request_validator
|
||||
BaseEndpoint.__init__(self)
|
||||
|
||||
@catch_errors_and_unavailability
|
||||
def create_userinfo_response(self, uri, http_method='GET', body=None, headers=None):
|
||||
"""Validate BearerToken and return userinfo from RequestValidator
|
||||
|
||||
The UserInfo Endpoint MUST return a
|
||||
content-type header to indicate which format is being returned. The
|
||||
content-type of the HTTP response MUST be application/json if the
|
||||
response body is a text JSON object; the response body SHOULD be encoded
|
||||
using UTF-8.
|
||||
"""
|
||||
request = Request(uri, http_method, body, headers)
|
||||
request.scopes = ["openid"]
|
||||
self.validate_userinfo_request(request)
|
||||
|
||||
claims = self.request_validator.get_userinfo_claims(request)
|
||||
if claims is None:
|
||||
log.error('Userinfo MUST have claims for %r.', request)
|
||||
raise errors.ServerError(status_code=500)
|
||||
|
||||
if isinstance(claims, dict):
|
||||
resp_headers = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
if "sub" not in claims:
|
||||
log.error('Userinfo MUST have "sub" for %r.', request)
|
||||
raise errors.ServerError(status_code=500)
|
||||
body = json.dumps(claims)
|
||||
elif isinstance(claims, str):
|
||||
resp_headers = {
|
||||
'Content-Type': 'application/jwt'
|
||||
}
|
||||
body = claims
|
||||
else:
|
||||
log.error('Userinfo return unknown response for %r.', request)
|
||||
raise errors.ServerError(status_code=500)
|
||||
log.debug('Userinfo access valid for %r.', request)
|
||||
return resp_headers, body, 200
|
||||
|
||||
def validate_userinfo_request(self, request):
|
||||
"""Ensure the request is valid.
|
||||
|
||||
5.3.1. UserInfo Request
|
||||
The Client sends the UserInfo Request using either HTTP GET or HTTP
|
||||
POST. The Access Token obtained from an OpenID Connect Authentication
|
||||
Request MUST be sent as a Bearer Token, per Section 2 of OAuth 2.0
|
||||
Bearer Token Usage [RFC6750].
|
||||
|
||||
It is RECOMMENDED that the request use the HTTP GET method and the
|
||||
Access Token be sent using the Authorization header field.
|
||||
|
||||
The following is a non-normative example of a UserInfo Request:
|
||||
|
||||
GET /userinfo HTTP/1.1
|
||||
Host: server.example.com
|
||||
Authorization: Bearer SlAV32hkKG
|
||||
|
||||
5.3.3. UserInfo Error Response
|
||||
When an error condition occurs, the UserInfo Endpoint returns an Error
|
||||
Response as defined in Section 3 of OAuth 2.0 Bearer Token Usage
|
||||
[RFC6750]. (HTTP errors unrelated to RFC 6750 are returned to the User
|
||||
Agent using the appropriate HTTP status code.)
|
||||
|
||||
The following is a non-normative example of a UserInfo Error Response:
|
||||
|
||||
HTTP/1.1 401 Unauthorized
|
||||
WWW-Authenticate: Bearer error="invalid_token",
|
||||
error_description="The Access Token expired"
|
||||
"""
|
||||
if not self.bearer.validate_request(request):
|
||||
raise errors.InvalidTokenError()
|
||||
if "openid" not in request.scopes:
|
||||
raise errors.InsufficientScopeError()
|
Loading…
Add table
Add a link
Reference in a new issue