The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.

Overview

Authlib

Build Status Coverage Status PyPI Version Maintainability Follow Twitter

The ultimate Python library in building OAuth and OpenID Connect servers. JWS, JWK, JWA, JWT are included.

Authlib is compatible with Python2.7+ and Python3.6+.

Authlib v1.0 will only support Python 3.6+.

Sponsors

If you want to quickly add secure token-based authentication to Python projects, feel free to check Auth0's Python SDK and free plan at auth0.com/developers.
A blogging and podcast hosting platform with minimal design but powerful features. Host your blog and Podcast with Typlog.com.

Fund Authlib to access additional features

Features

Generic, spec-compliant implementation to build clients and providers:

Connect third party OAuth providers with Authlib built-in client integrations:

Build your own OAuth 1.0, OAuth 2.0, and OpenID Connect providers:

Useful Links

  1. Homepage: https://authlib.org/.
  2. Documentation: https://docs.authlib.org/.
  3. Purchase Commercial License: https://authlib.org/plans.
  4. Blog: https://blog.authlib.org/.
  5. Twitter: https://twitter.com/authlib.
  6. StackOverflow: https://stackoverflow.com/questions/tagged/authlib.
  7. Other Repositories: https://github.com/authlib.
  8. Subscribe Tidelift: https://tidelift.com/subscription/pkg/pypi-authlib.

Security Reporting

If you found security bugs, please do not send a public issue or patch. You can send me email at [email protected]. Attachment with patch is welcome. My PGP Key fingerprint is:

72F8 E895 A70C EBDF 4F2A DFE0 7E55 E3E0 118B 2B4C

Or, you can use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

License

Authlib offers two licenses:

  1. BSD (LICENSE)
  2. COMMERCIAL-LICENSE

Companies can purchase a commercial license at Authlib Plans.

If your company is creating a closed source OAuth provider, it is strongly suggested that your company purchasing a commercial license.

Support

If you need any help, you can always ask questions on StackOverflow with a tag of "Authlib". DO NOT ASK HELP IN GITHUB ISSUES.

We also provide commercial consulting and supports. You can find more information at https://authlib.org/support.

Comments
  • AGPL?!

    AGPL?!

    I just realized that this library is AGPL-licensed - quite unexpected considering that its predecessors like flask-oauthlib and oauthlib are BSD-licensed, and e.g. flask-oauthlib strongly recommends people to authlib instead.

    While I completely understand that you want to make money with this library when people use it in commercial/closed-source software, the fact that it's AGPL and thus very viral seems problematic:

    For example, many open source projects nowadays use a more liberal license like MIT or BSD. And while IANAL, I'm pretty sure any such projects are currently excluded from using your library, since you cannot use GPL software in MIT/BSD-licensed application...

    ...which this is truly unfortunate, since AFAIK there is no other decent implementation of OAuth providers for Python out there - and many webapps do include OAuth provider functionality nowadays! And we all know what happens when people start implementing their own security code... usually it won't be as secure as it should be.

    opened by ThiefMaster 45
  • CSRF Warning! State not equal in request and response

    CSRF Warning! State not equal in request and response

    Describe the bug

    It happens when using authlib to configure Keycloak for Apache Superset. Everything works perfectly up until redirecting back from Keycloak to Superset.

    Error Stacks

    Traceback (most recent call last):
      File "/home/abc/.local/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
        response = self.full_dispatch_request()
      File "/home/abc/.local/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/home/abc/.local/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/home/abc/.local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
        raise value
      File "/home/abc/.local/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
        rv = self.dispatch_request()
      File "/home/abc/.local/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/home/abc/.local/lib/python3.8/site-packages/flask_appbuilder/security/views.py", line 681, in oauth_authorized
        resp = self.appbuilder.sm.oauth_remotes[provider].authorize_access_token()
      File "/usr/local/lib/python3.8/site-packages/authlib/integrations/flask_client/remote_app.py", line 74, in authorize_access_token
        params = self.retrieve_access_token_params(flask_req, request_token)
      File "/usr/local/lib/python3.8/site-packages/authlib/integrations/base_client/base_app.py", line 145, in retrieve_access_token_params
        params = self._retrieve_oauth2_access_token_params(request, params)
      File "/usr/local/lib/python3.8/site-packages/authlib/integrations/base_client/base_app.py", line 126, in _retrieve_oauth2_access_token_params
        raise MismatchingStateError()
    authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response.
    

    To Reproduce

    A minimal example to reproduce the behavior: This is my code: In superset_config.py

    AUTH_USER_REGISTRATION = True
    AUTH_USER_REGISTRATION_ROLE = 'Public'
    CSRF_ENABLED = True
    ENABLE_PROXY_FIX = True
    OAUTH_PROVIDERS = [
        {
            'name': 'keycloak',
            'token_key': 'access_token',
            'icon': 'fa-icon',
            'remote_app': {
                'client_id': CLIENT_ID,
                'client_secret': CLIENT_SECRET,
                'client_kwargs': {
                    'scope': 'openid email profile'
                },
                'access_token_method': 'POST',
                'api_base_url': 'https://KEYCLOAK_URL/auth/realms/REALM_NAME/protocol/openid-connect/',
                'access_token_url': 'https://KEYCLOAK_URL/auth/realms/REALM_NAME/protocol/openid-connect/token',
                'authorize_url': 'https://KEYCLOAK_URL/auth/realms/REALM_NAME/protocol/openid-connect/auth',
            },
        }
    ]
    CUSTOM_SECURITY_MANAGER = OIDCSecurityManager
    

    In extended_security.py

    
    
    class OIDCSecurityManager(SupersetSecurityManager):
        def get_oauth_user_info(self, provider, response=None):
            if provider == 'keycloak':
                me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
                return {
                    "first_name": me.data.get("given_name", ""),
                    "last_name": me.data.get("family_name", ""),
                    "email": me.data.get("email", "")
                }
    

    Expected behavior

    Suerpset redirect user to keycloak authentication site as expected. Upon finishing authenticating and getting redirected back to superset, CSRF Warning! State not equal in request and response occur.

    Environment: Docker:

    • Python Version: 3.8
    • Authlib Version: 0.15.4

    Additional context

    Tried on different browser (chrome, firefox, edge, etc.), clearing cookies, etc., but the error is still there. Would very appreciate some help.

    bug 
    opened by nl2412 22
  • Allowing multiple authentication flows in parallel (e.g., in different tabs)

    Allowing multiple authentication flows in parallel (e.g., in different tabs)

    Is your feature request related to a problem? Please describe.

    We currently use authlib.integrations.flask_client to authenticate users against Auth0, where they can log in via different connection types (e.g., GitHub, Google, etc.). But users sometimes initiate multiple authentication flows in parallel, as by command- or control-clicking multiple links, each of which opens in a new tab. Even if the user logs in successfully to each of those tabs, each tab (except for the most recently opened one) ultimately errs with:

    authlib.integrations.base_client.errors.MismatchingStateError: 
    mismatching_state: CSRF Warning! State not equal in request and response
    

    That seems to be the result of Authlib using a single session key (e.g., _name_authlib_state_) to implement CSRF protection, per https://github.com/lepture/authlib/blob/master/authlib/integrations/flask_client/integration.py#L15-L21.

    Because each tab has a new value for state, previously opened tabs' state values are clobbered in Flask's session.

    Describe the solution you'd like

    Might it make sense to use unique session keys instead so that tabs don't share (and clobber each other's) state? Similarly for _name_authlib_redirect_uri_ and _name_authlib_nonce_? E.g., instead of, in pseudocode,

    session["_name_authlib_state_"] = "ABC"
    session["_name_authlib_redirect_uri_"] = "https://example.com/callback"
    session["_name_authlib_nonce_"] = "XYZ"
    

    perhaps an approach along these lines, whereby the key includes the unique state value?

    session["_name_authlib_ABC_"] = {
        "redirect_uri": "https://example.com/callback",
        "nonce": "XYZ"
    }
    

    Describe alternatives you've considered

    Instead of authlib.integrations.flask_client, should we perhaps use requests_client.OAuth2Session instead to achieve this behavior? Would we need to validate state, redirect_uri, and nonce ourselves, though, and also validate the ID token returned from Auth0?

    Is a simpler approach already possible perhaps?

    Additional context

    If a user opens multiple tabs because they've command- or control-clicked multiple links (each of which requires authentication), it's indeed intentional that we want them to authenticate in each of those tabs (especially since their choice of connection type on Auth0's end might differ per tab). We wouldn't want one tab, upon encountering a MismatchingStateError, simply to check whether the user has logged in via another tab and allow the user to proceed.

    Thank you!

    opened by dmalan 18
  • PKCE client authentication in shared public/private server

    PKCE client authentication in shared public/private server

    This issue is similar to my other reported issue #115 but essentially in an authorization server where applications are both public and private it isn't possible to natively authenticate to the token server as a public and private client depending on type of authorization request.

    The only way to achieve this currently is to extend the client auth methods with a custom authentication scheme:

    def authenticate_rfc7636(query_client, request):
        data = request.form
        code_verifier = data.get('code_verifier')
        if code_verifier:
            return authenticate_none(query_client, request)
    

    This works because rfc7636 always runs validate_code_verifier after after_validate_token_request, which validates the code verifier provided.

    spec 
    opened by night 16
  • Cyclic dependencies when using AuthorizationServer(Client, app)

    Cyclic dependencies when using AuthorizationServer(Client, app)

    At least in my case, when creating an AuthorizationServer, it requires the Client model. This has the requirement that the models be imported. However, since the models themselves also import __init__.py through from .. import db, login_manager, it creates a cyclic include.

    Due to this constraint, the next best option is to use flask-oauthlib library. It might make sense to address this issue, either in the documentation or in the code architecturally.

    opened by moritz89 16
  • Add Starlette client (#148)

    Add Starlette client (#148)

    This commit adds a new Starlette client along with documentation and tests. The Starlette client is suitable for use with frameworks that build on top of Starlette such as FastAPI and Bocadillo.

    This implements #148.

    What kind of change does this PR introduce? (check at least one)

    • [ ] Bugfix
    • [x] Feature
    • [ ] Code style update
    • [ ] Refactor
    • [ ] Other, please describe:

    Does this PR introduce a breaking change? (check one)

    • [ ] Yes
    • [x] No

    • [x] You consent that the copyright of your pull request source code belongs to Authlib's author.
    opened by jonathanunderwood 14
  • Allow passing in additional jwt headers

    Allow passing in additional jwt headers

    What kind of change does this PR introduce? (check at least one)

    • [ ] Bugfix
    • [x] Feature
    • [ ] Code style update
    • [ ] Refactor
    • [ ] Other, please describe:

    Does this PR introduce a breaking change? (check one)

    • [ ] Yes
    • [x] No

    • [x] You consent that the copyright of your pull request source code belongs to Authlib's author.

    Referencing https://github.com/lepture/authlib/issues/391

    I'd like to pass in addtional JWT headers into the client assertion, such as the kid so the recipient of the token can find the corresponding key at the registered JWKS endpoint.

    Describe the solution you'd like

    When setting up an PrivateKeyJWT() instance to register as client auth method, I'd like to pass in additional JWT headers such as the kid.

    opened by janwijbrand 12
  • Twitter OAuth Not working due to missing 'request_token' parameter

    Twitter OAuth Not working due to missing 'request_token' parameter

    Describe the bug

    oauth.twitter.authorize_access_token(request) is normally called in the callback function. The request object usually has a request_token parameter in its query parameters. However, Twitter's 3-legged OAuth process, described here: https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens

    Does not return a request_token parameter. Instead it returns oauth_token and oauth_verifier. Both of these are expected to be passed back to the twitter's auth endpoint to get the user's tokens.

    The problem comes in function fetch_access_token in authlib\integrations\base_client\async_app.py. That function contains the following code:

                    if request_token is None:
                        raise MissingRequestTokenError()
                    # merge request token with verifier
                    token = {}
                    token.update(request_token)
                    token.update(params)
                    client.token = token
    

    Since twitter doesn't have a request_token, the MissingRequestTokenError() is raised and the authorize process fails. This is an error for twitter because twitter doesn't require a request_token. I commented out the lines 1, 2, and 5 from above, and then twitter oauth worked fine, returning the client's token as expected.

    FWIW, I use loginpass but this defines the twitter metadata the same as is shown in the examples, so I don't think that's the source of the error.

    Is there a way to specify that for twitter, this function should just skip the request_token parameter? More generally, is there a way to specify what query parameters are expected to be returned for each endpoint, so that in the future, other endpoints that return non-standard parameters can be accommodated?

    Error Stacks

    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 389, in run_asgi
        result = await app(self.scope, self.receive, self.send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
        return await self.app(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\fastapi\applications.py", line 179, in __call__
        await super().__call__(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\applications.py", line 111, in __call__
        await self.middleware_stack(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
        raise exc from None
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
        await self.app(scope, receive, _send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\middleware\cors.py", line 78, in __call__
        await self.app(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\middleware\sessions.py", line 75, in __call__
        await self.app(scope, receive, send_wrapper)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\exceptions.py", line 82, in __call__
        raise exc from None
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\exceptions.py", line 71, in __call__
        await self.app(scope, receive, sender)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\routing.py", line 566, in __call__
        await route.handle(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\routing.py", line 227, in handle
        await self.app(scope, receive, send)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\starlette\routing.py", line 41, in app
        response = await func(request)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\fastapi\routing.py", line 182, in app
        raw_response = await run_endpoint_function(
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\fastapi\routing.py", line 133, in run_endpoint_function
        return await dependant.call(**values)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\app\api\api_v1\endpoints\link_accounts.py", line 156, in auth_twitter
        token = await oauth.twitter.authorize_access_token(request)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\authlib\integrations\starlette_client\integration.py", line 64, in authorize_access_token
        return await self.fetch_access_token(**params)
      File "C:\Users\mraju\PycharmProjects\api-server-useraccounts\venv\lib\site-packages\authlib\integrations\base_client\async_app.py", line 90, in fetch_access_token
        raise MissingRequestTokenError()
    authlib.integrations.base_client.errors.MissingRequestTokenError: missing_request_token: 
    

    To Reproduce

    @router.get('/twitter/login')
    async def login_twitter(request: Request) -> Any:
        redirect_uri = request.url_for('auth_twitter')
        return await oauth.twitter.authorize_redirect(request, redirect_uri)
    
    
    @router.get('/twitter/callback')
    async def auth_twitter(request: Request):
        token = await oauth.twitter.authorize_access_token(request)
    

    Expected behavior

    A clear and concise description of what you expected to happen.

    Environment:

    • OS: Windows
    • Python Version: 3.9.0
    • Authlib Version: 0.15.2

    Additional context

    Add any other context about the problem here.

    bug 
    opened by hashcutdev 12
  • Same input causes exception in python 3.8.3 but not in python 3.6.8

    Same input causes exception in python 3.8.3 but not in python 3.6.8

    Describe the bug

    An input for authlib.jose.jwt.decode() causes an exception on python 3.8.3 while it works on python 3.6.8 .

    I'm using:

    from authlib.jose import jwt
    jwt.decode(mytoken, key=mykey, claims_options=something)
    

    The causing parameter is key. In my case, the (shortened) value is :

    {
      "keys": [
        {
          "kid": "something2",
          "kty": "RSA",
          "alg": "RS256",
          "use": "sig",
          "n": "something3",
          "e": "AQAB",
          "x5c": ["something4"],
          "x5t": "something5",
          "x5t#S256": "something6"
        }
      ]
    }
    

    However, if I set mykey to the key in the inner list:

    {
          "kid": "something2",
          "kty": "RSA",
          "alg": "RS256",
          "use": "sig",
          "n": "something3",
          "e": "AQAB",
          "x5c": ["something4"],
          "x5t": "something5",
          "x5t#S256": "something6"
        }
    

    then authlib accepts the input for both, python 3.6.8 and 3.8.3.

    Error Stacks

    [...]
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7519/jwt.py", line 98, in decode
        data = self._jws.deserialize_compact(s, load_key, decode_payload)
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7515/jws.py", line 102, in deserialize_compact
        algorithm, key = self._prepare_algorithm_key(jws_header, payload, key)
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7515/jws.py", line 258, in _prepare_algorithm_key
        key = algorithm.prepare_key(key)
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7518/_cryptography_backends/_jws.py", line 41, in prepare_key
        return RSAKey.import_key(raw_data)
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7518/_cryptography_backends/_keys.py", line 116, in import_key
        return import_key(
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7518/_cryptography_backends/_keys.py", line 277, in import_key
        cls.check_required_fields(raw)
      File "/Users/njjn/.pyenv/versions/demo2/lib/python3.8/site-packages/authlib/jose/rfc7517/models.py", line 120, in check_required_fields
        raise ValueError('Missing required field: "{}"'.format(k))
    ValueError: Missing required field: "e"
    

    To Reproduce

    (untested): get a valid key and put it in the structure as depicted in my example above.

    Expected behavior

    The same input gets accepted without errors for both python versions.

    Environment:

    • OS: macos/linux
    • Python Version: 3.8.3
    • Authlib Version: v0.15
    bug 
    opened by juergen-kaiser-by 12
  • Inconsistency licence statements between README and LICENSE

    Inconsistency licence statements between README and LICENSE

    The README states

    License
    
    Authlib offers two licenses:
    
        BSD for open source projects
        Commercial license for closed source projects
    

    however, the LICENSE is a BSD license, which is compliant with closed source (redistribution). As it stands, I read this as

    If I develop a close source project, I must buy a commercial license; if it is an open source, I can use BSD.

    If this is the case, then this project is not BSD licensed, as its actual license is

    If usage in open source, you can use it under the terms of BSD; else, you must buy a commercial license

    I propose that we clarify what exactly do we mean with Commercial license for closed source projects.

    bug 
    opened by jorgecarleitao 11
  • error w/ google oauth

    error w/ google oauth

    Hello, I can't made a successful auth against google oauth because an error (that seems related or identical to https://github.com/authlib/loginpass/issues/47).

    Here is the relevant code:

    config = Config(".env")  # pylint: disable=invalid-name
    oauth = OAuth(config)
    
    CONF_URL = 'https://accounts.google.com/.well-known/openid-configuration'
    oauth.register(
        name='google',
        server_metadata_url=CONF_URL,
        client_kwargs={
            'scope': 'openid email profile'
        }
    )
    
    async def login(request):
        redirect_uri = request.url_for('auth')
        return await oauth.google.authorize_redirect(request, redirect_uri)
    
    async def auth(request):
        logging.critical(request.headers)
        token = await oauth.google.authorize_access_token(request)
        user = await oauth.google.parse_id_token(request, token)
        request.session['user'] = dict(user)
        return RedirectResponse(url='/')
    
    ROUTES = [
        Route('/login', endpoint=login),
        Route('/auth', endpoint=auth),
    ]
    
    app = Starlette(debug=True, routes=ROUTES)  # pylint: disable=invalid-name
    

    when /auth endpoint is hit after a successful authentication, I get this traceback (first line is mine):

    [osso] CRITICAL: Headers({'host': 'osso.dev.scimmia.net', 'x-request-id': '299db1f2a6d8f187459083ed590d4adb', 'x-real-ip': '10.42.0.1', 'x-forwarded-for': '10.42.0.1', 'x-forwarded-host': 'osso.dev.scimmia.net', 'x-forwarded-port': '443', 'x-forwarded-proto': 'https', 'x-scheme': 'https', 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'accept-language': 'en-US,en;q=0.5', 'accept-encoding': 'gzip, deflate, br', 'referer': 'https://accounts.google.com/', 'dnt': '1', 'upgrade-insecure-requests': '1'})
    [osso] INFO:     10.42.0.1:0 - "GET /auth?state=VNyCSjjCXSojWBTqNjsm3XlxBSJEgg&code=4%2FwwEnVamW5jzr4hOz4agsa1kjrKBlCOrMJTdO0pbFM9nq9qDbJ7-riJQ4Sh9TeokDyvz47FnRtY4DQsMMNH3N_II&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=consent HTTP/1.1" 500 Internal Server Error
    [osso] ERROR:    Exception in ASGI application
    [osso] Traceback (most recent call last):
    [osso]   File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    [osso]     result = await app(self.scope, self.receive, self.send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    [osso]     return await self.app(scope, receive, send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/applications.py", line 102, in __call__
    [osso]     await self.middleware_stack(scope, receive, send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__
    [osso]     raise exc from None
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
    [osso]     await self.app(scope, receive, _send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette_authlib/middleware.py", line 122, in __call__
    [osso]     await self.app(scope, receive, send_wrapper)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__
    [osso]     raise exc from None
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
    [osso]     await self.app(scope, receive, sender)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 550, in __call__
    [osso]     await route.handle(scope, receive, send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle
    [osso]     await self.app(scope, receive, send)
    [osso]   File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 41, in app
    [osso]     response = await func(request)
    [osso]   File "./osso/app.py", line 79, in auth
    [osso]     token = await oauth.google.authorize_access_token(request)
    [osso]   File "/usr/local/lib/python3.7/site-packages/authlib/integrations/starlette_client/integration.py", line 58, in authorize_access_token
    [osso]     return await self.fetch_access_token(**params)
    [osso]   File "/usr/local/lib/python3.7/site-packages/authlib/integrations/base_client/async_app.py", line 105, in fetch_access_token
    [osso]     token = await client.fetch_token(token_endpoint, **kwargs)
    [osso]   File "/usr/local/lib/python3.7/site-packages/authlib/integrations/httpx_client/oauth2_client.py", line 120, in _fetch_token
    [osso]     return self.parse_response_token(resp.json())
    [osso]   File "/usr/local/lib/python3.7/site-packages/authlib/oauth2/client.py", line 348, in parse_response_token
    [osso]     self.handle_error(error, description)
    [osso]   File "/usr/local/lib/python3.7/site-packages/authlib/integrations/httpx_client/oauth2_client.py", line 76, in handle_error
    [osso]     raise OAuthError(error_type, error_description)
    [osso] authlib.common.errors.AuthlibBaseError: invalid_request: Missing parameter: redirect_uri
    

    Expected behavior

    A successful login via google oauth

    Environment:

    • OS: python:3.7-slim docker image (alpine)
    • Authlib Version: 0.14.1

    Thank you, ciao!

    bug 
    opened by aogier 11
  • Azure OAuth CSRF State Not Equal Error

    Azure OAuth CSRF State Not Equal Error

    Describe the bug

    When I try to use Azure OAuth to log into my Airflow application, instead of logging me in I am sent back to the login page with a CSRF state mismatch error.

    Error Stacks

    [2022-11-28 22:04:58,744] {views.py:659} ERROR - Error authorizing OAuth access token: mismatching_state: CSRF Warning! State not equal in request and response.
    airflow-web [2022-11-28 22:04:58,744] {views.py:659} ERROR - Error authorizing OAuth access token: mismatching_state: CSRF Warning! State not equal in request and response.
    

    To Reproduce

    I am running Airflow 2.4.3 on Kubernetes pods using the airflow community helm chart 8.6.1(https://github.com/airflow-helm/charts) and python 3.8.15. To use Azure OAuth configuration with Airflow, I have created the webserver_config file to do so:

    from flask_appbuilder.security.manager import AUTH_OAUTH
    from airflow.www.security import AirflowSecurityManager
    import logging
    from typing import Dict, Any, List, Union
    import os
    import sys
    
    #Add this as a module to pythons path
    sys.path.append('/opt/airflow')
    
    log = logging.getLogger(__name__)
    log.setLevel(os.getenv("AIRFLOW__LOGGING__FAB_LOGGING_LEVEL", "DEBUG"))
    
    class AzureCustomSecurity(AirflowSecurityManager):
        # In this example, the oauth provider == 'azure'.
        # If you ever want to support other providers, see how it is done here:
        # https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py#L550
        def get_oauth_user_info(self, provider, resp):
            # Creates the user info payload from Azure.
            # The user previously allowed your app to act on their behalf,
            #   so now we can query the user and teams endpoints for their data.
            # Username and team membership are added to the payload and returned to FAB.
            if provider == "azure":
                log.debug("Azure response received : {0}".format(resp))
                id_token = resp["id_token"]
                log.debug(str(id_token))
                me = self._azure_jwt_token_parse(id_token)
                log.debug("Parse JWT token : {0}".format(me))
                return {
                    "name": me.get("name", ""),
                    "email": me["upn"],
                    "first_name": me.get("given_name", ""),
                    "last_name": me.get("family_name", ""),
                    "id": me["oid"],
                    "username": me["oid"],
                    "role_keys": me.get("roles", []),
                }
    
    # Adding this in because if not the redirect url will start with http and we want https
    os.environ["AIRFLOW__WEBSERVER__ENABLE_PROXY_FIX"] = "True"
    WTF_CSRF_ENABLED = False
    CSRF_ENABLED = False
    AUTH_TYPE = AUTH_OAUTH
    AUTH_ROLES_SYNC_AT_LOGIN = True  # Checks roles on every login
    # Make sure to replace this with the path to your security manager class
    FAB_SECURITY_MANAGER_CLASS = "webserver_config.AzureCustomSecurity"
    # a mapping from the values of `userinfo["role_keys"]` to a list of FAB roles
    AUTH_ROLES_MAPPING = {
        "airflow_dev_admin": ["Admin"],
        "airflow_dev_op": ["Op"],
        "airflow_dev_user": ["User"],
        "airflow_dev_viewer": ["Viewer"]
        }
    # force users to re-auth after 30min of inactivity (to keep roles in sync)
    PERMANENT_SESSION_LIFETIME = 1800
    # If you wish, you can add multiple OAuth providers.
    OAUTH_PROVIDERS = [
        {
            "name": "azure",
            "icon": "fa-windows",
            "token_key": "access_token",
            "remote_app": {
                "client_id": "CLIENT_ID",
                "client_secret": 'AZURE_DEV_CLIENT_SECRET',
                "api_base_url": "https://login.microsoftonline.com/TENANT_ID",
                "request_token_url": None,
                'request_token_params': {
                    'scope': 'openid email profile'
                },
                "access_token_url": "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token",
                "access_token_params": {
                    'scope': 'openid email profile'
                },
                "authorize_url": "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/authorize",
                "authorize_params": {
                    'scope': 'openid email profile',
                },
                'jwks_uri':'https://login.microsoftonline.com/common/discovery/v2.0/keys',
            },
        },
    ]
    

    Expected behavior

    When you hit the login button it should log me in to the airflow instance.

    Environment:

    • OS: Debian GNU/Linux 11 (bullseye)
    • Python Version: 3.8.15
    • Authlib Version: 1.1.0

    Additional context

    This was working just fine, but when we upgraded from airflow 2.2.5 to 2.4.3 this issue arose. Here are some current versions of libraries I have installed:

    Airflow==2.4.3 Authlib==1.1.0 Flask-AppBuilder==4.1.4 Flask-Babel==2.0.0 Flask-Caching==2.0.1 Flask-JWT-Extended==4.4.4 Flask-Login==0.6.2 Flask-SQLAlchemy==2.5.1 Flask-Session==0.4.0 Flask-WTF==1.0.1 Flask==2.2.2

    I have posted this issue in airflow as well as FAB and still have not been able to find out how to solve

    question 
    opened by ahipp13 9
  • Incorrect signature for x-www-form-urlencoded POST requests with httpx OAuth1 client

    Incorrect signature for x-www-form-urlencoded POST requests with httpx OAuth1 client

    Describe the bug

    When using the exactly same credentials and API call signatures, the requests client could access protected resources from OAuth protected API, while the signature of requests made by httpx client is rejected.

    This only happens for POST requests which sends non-binary data (Content-Type will be x-www-form-urlencoded).

    Error Stacks

    Error are raised at server side and is service-specific (depends on how API services respond to invalid OAuth signatures) so there's no error stack.

    To Reproduce

    from authlib.integrations.requests_client import OAuth1Session
    from authlib.integrations.httpx_client import OAuth1Client
    
    
    CLIENT_ID = '<client_id>'
    CLIENT_SECRET = '<client_secret>'
    TOKEN = '<token>'
    TOKEN_SECRET = '<token_secret>'
    ENDPOINT = '<protected_resource_api_endpoint>'
    REQUEST_BODY = {'foo': 'bar'}
    
    requests_client = OAuth1Session(CLIENT_ID, CLIENT_SECRET, token=TOKEN, token_secret=TOKEN_SECRET)
    httpx_client = OAuth1Client(CLIENT_ID, CLIENT_SECRET, token=TOKEN, token_secret=TOKEN_SECRET)
    
    
    r = requests_client.post(ENDPOINT, data=REQUEST_BODY)
    print('REQUEST ', r.json(), '\n')
    
    r = httpx_client.post(ENDPOINT, data=REQUEST_BODY)
    print('HTTPX ', r.json())
    

    Reproducing the issue with the above script requires access to OAuth1.0 protected API resources. In the above example, the requests client could access the protected resource without a problem, while the httpx client is rejected by an incorrect signature error.

    Expected behavior

    Both requests client and httpx client should have access to the protected resource when authenticated with access token.

    Environment:

    • OS: Ubuntu 22.04
    • Python Version: 3.10.6
    • Authlib Version: 1.2.0
    • httpx version: 0.23.1

    Additional context

    I've tried to fix the issue and the fix seems working on my end, though I've only tested httpx OAuth1 client. Not sure whether it will break another clients or not.

    bug 
    opened by shc261392 0
  • Data loss when using httpx OAuth1 client to send files with POST requests

    Data loss when using httpx OAuth1 client to send files with POST requests

    Describe the bug

    When sending files in a POST request using httpx client, all binary data (the files) are lost.

    Error Stacks

    There is no error stack for this issue, since this is an issue only detectable from server-side or only when the server side returns meaningful error responses. To demonstrate the case, I've added the full steps and scripts to reproduce the issue in the next section.

    To Reproduce

    Scripts for issue reproduction:

    1. Main script
    2. Debug server. You can use any other tools that can act as the server to receive the request instead, this one is just attached for convenience.

    Steps to reproduce:

    1. Run the debug server
    2. Run the main script. The main script includes two consecutive requests, one using the authlib requests client and one using the httpx client, so that we could compare the normal one with the corrupted one.

    requests client

    Received header Content-Length:  146
    Received actual bytes:  146
    127.0.0.1 - - [17/Dec/2022 08:39:09] "POST / HTTP/1.1" 200 -
    

    httpx client

    Received header Content-Length:  0
    Received actual bytes:  0
    127.0.0.1 - - [17/Dec/2022 08:39:09] "POST / HTTP/1.1" 200 -
    

    It's obvious the binary data are lost when using httpx client.

    Expected behavior

    The request data should not be corrupted. httpx client should behaves like requests client when using the same inputs and configurations.

    Environment:

    • OS: Ubuntu 22.04
    • Python Version: 3.10.6
    • Authlib Version: 1.2.0
    • httpx Version: 0.23.1

    Additional context

    I've tried to fix this issue and the fix seems working. Perhaps I could submit a pull request if this issue could be verified true.

    bug 
    opened by shc261392 0
  • `PrivateKeyJWT.headers` field is not passed to `private_key_jwt_sign` function call in `PrivateKeyJWT.sign` method

    `PrivateKeyJWT.headers` field is not passed to `private_key_jwt_sign` function call in `PrivateKeyJWT.sign` method

    Describe the bug

    In commit 49c5556d8b2c7e4b8939e502fefd816bf766dfc3 headers parameter got re-introduced (previously known as header) and it is passed to client_secret_jwt_sign function call in ClientSecretJWT.sign method, but it is not passed to private_key_jwt_sign function call in PrivateKeyJWT.sign method, why is it so?

    Also both client_secret_jwt_sign & private_key_jwt_sign eventually call sign_jwt_bearer_assertion which doesn't have headers parameter, but only header, so it looks to be skipped, is it expected?

    Expected behavior

    headers parameter is passed to private_key_jwt_sign function call in PrivateKeyJWT.sign method

    class PrivateKeyJWT(ClientSecretJWT):
        ...
        def sign(self, auth, token_endpoint):
            return private_key_jwt_sign(
                auth.client_secret,
                client_id=auth.client_id,
                token_endpoint=token_endpoint,
                claims=self.claims,
                header=self.headers,
                alg=self.alg,
            )
    

    Environment:

    • OS: OS-independent
    • Python Version: Python-independent
    • Authlib Version: 1.2.0
    bug 
    opened by lycantropos 0
  • Removed `request_invalid` and `token_revoked` methods

    Removed `request_invalid` and `token_revoked` methods

    What kind of change does this PR introduce? (check at least one)

    This removes unused methods definition and documentation.

    • [ ] Bugfix
    • [ ] Feature
    • [ ] Code style update
    • [x] Refactor
    • [ ] Other, please describe:

    Does this PR introduce a breaking change? (check one)

    • [ ] Yes
    • [x] No

    • [x] You consent that the copyright of your pull request source code belongs to Authlib's author.
    opened by azmeuk 0
  • RFC7591: Use default values for 'response_types' and 'grant_types'

    RFC7591: Use default values for 'response_types' and 'grant_types'

    The RFC7591 dynamic client registration indicates default values for response_types and grant_types:

    • If omitted, the default is that the client will use only the "code" response type.
    • If omitted, the default behavior is that the client will use only the "authorization_code" Grant Type.

    This is a better attempt than #509

    What kind of change does this PR introduce? (check at least one)

    • [x] Bugfix
    • [ ] Feature
    • [ ] Code style update
    • [ ] Refactor
    • [ ] Other, please describe:

    Does this PR introduce a breaking change? (check one)

    • [ ] Yes
    • [x] No

    • [x] You consent that the copyright of your pull request source code belongs to Authlib's author.
    opened by azmeuk 0
Releases(v1.2.0)
  • v1.2.0(Dec 6, 2022)

    • Not passing request.body to ResourceProtector, #485.
    • Use flask.g instead of _app_ctx_stack, #482.
    • Add headers parameter back to ClientSecretJWT, #457.
    • Always passing realm parameter in OAuth 1 clients, #339.
    • Implemented RFC7592 Dynamic Client Registration Management Protocol, #505`
    • Add default_timeout for requests OAuth2Session and AssertionSession.
    • Deprecate jwk.loads and jwk.dumps
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Nov 9, 2022)

    This release contains breaking changes and security fixes.

    • Allow to pass claims_options to Framework OpenID Connect clients, via #446 by @Galaxy102
    • Fix .stream with context for HTTPX OAuth clients, via #465 by @bjoernmeier
    • Fix Starlette OAuth client for cache store, via #478 by @haggen

    Breaking changes:

    • Raise InvalidGrantError for invalid code, redirect_uri and no user errors in OAuth 2.0 server.
    • The default authlib.jose.jwt would only work with JSON Web Signature algorithms, if you would like to use JWT with JWE algorithms, please pass the algorithms parameter:
    jwt = JsonWebToken(['A128KW', 'A128GCM', 'DEF'])
    

    Security fixes for JOSE module

    • CVE-2022-39175
    • CVE-2022-39174
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Apr 6, 2022)

    • Fix authenticate_none method, via #438.
    • Allow to pass in alternative signing algorithm to RFC7523 authentication methods via #447.
    • Fix missing_token for Flask OAuth client, via #448.
    • Allow openid in any place of the scope, via #449.
    • Security fix for validating essential value on blank value in JWT, via #445.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Mar 15, 2022)

    We have dropped support for Python 2 in this release. We have removed built-in SQLAlchemy integration.

    OAuth Client Changes:

    The whole framework client integrations have been restructured, if you are using the client properly, e.g. oauth.register(...), it would work as before.

    OAuth Provider Changes:

    In Flask OAuth 2.0 provider, we have removed the deprecated OAUTH2_JWT_XXX configuration, instead, developers should define .get_jwt_config on OpenID extensions and grant types.

    SQLAlchemy integrations has been removed from Authlib. Developers should define the database by themselves.

    JOSE Changes

    • JWS has been renamed to JsonWebSignature
    • JWE has been renamed to JsonWebEncryption
    • JWK has been renamed to JsonWebKey
    • JWT has been renamed to JsonWebToken

    The "Key" model has been re-designed, checkout the JSON Web Key for updates.

    Added ES256K algorithm for JWS and JWT.

    Breaking Changes: find how to solve the deprecate issues via https://git.io/JkY4f

    Source code(tar.gz)
    Source code(zip)
  • v0.15.5(Oct 18, 2021)

  • v0.15.4(Jul 17, 2021)

    Security fix when JWT claims is None.

    For example, JWT payload has iss=None:

    {
      "iss": None,
      ...
    }
    

    But we need to decode it with claims:

    claims_options = {
      'iss': {'essential': True, 'values': ['required']}
    }
    jwt.decode(token, key, claims_options=claims_options)
    

    It didn't raise an error before this fix.

    Source code(tar.gz)
    Source code(zip)
  • v0.15.3(Jan 15, 2021)

  • v0.15.2(Oct 18, 2020)

  • v0.15.1(Oct 14, 2020)

  • v0.15(Oct 10, 2020)

    This is the last release before v1.0. In this release, we added more RFCs implementations and did some refactors for JOSE:

    • RFC8037: CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)
    • RFC7638: JSON Web Key (JWK) Thumbprint

    We also fixed bugs for integrations:

    • Fixed support for HTTPX>=0.14.3
    • Added OAuth clients of HTTPX back via #270
    • Fixed parallel token refreshes for HTTPX async OAuth 2 client
    • Raise OAuthError when callback contains errors via #275

    Breaking Change:

    1. The parameter algorithms in JsonWebSignature and JsonWebEncryption are changed. Usually you don't have to care about it since you won't use it directly.
    2. Whole JSON Web Key is refactored, please check JSON Web Key (JWK)
    Source code(tar.gz)
    Source code(zip)
  • v0.14.3(May 18, 2020)

    • Fix HTTPX integration via #232 and #233.
    • Add "bearer" as default token type for OAuth 2 Client.
    • JWS and JWE don't validate private headers by default.
    • Remove none auth method for authorization code by default.
    • Allow usage of user provided code_verifier via #216.
    • Add introspect_token method on OAuth 2 Client via #224.
    Source code(tar.gz)
    Source code(zip)
  • v0.14.2(May 6, 2020)

    • Fix OAuth 1.0 client for starlette.
    • Allow leeway option in client parse ID token via #228.
    • Fix OAuthToken when expires_at or expires_in is 0 via #227.
    • Fix auto refresh token logic.
    • Load server metadata before request.
    Source code(tar.gz)
    Source code(zip)
  • v0.14.1(May 6, 2020)

  • v0.14(Feb 11, 2020)

    In this release, Authlib has introduced a new way to write framework integrations for clients.

    Bug fixes and enhancements in this release:

    • Fix HTTPX integrations due to HTTPX breaking changes
    • Fix ES algorithms for JWS
    • Allow user given nonce via #180.
    • Fix OAuth errors get_headers leak.
    • Fix code_verifier via #165.

    Breaking Change: drop sync OAuth clients of HTTPX.

    Source code(tar.gz)
    Source code(zip)
  • v0.13(Nov 11, 2019)

    This is the release that makes Authlib one more step close to v1.0. We did a huge refactor on our integrations. Authlib believes in monolithic design, it enables us to design the API to integrate with every framework in the best way. In this release, Authlib has re-organized the folder structure, moving every integration into the integrations folder. It makes Authlib to add more integrations easily in the future.

    RFC implementations and updates in this release:

    • RFC7591: OAuth 2.0 Dynamic Client Registration Protocol
    • RFC8628: OAuth 2.0 Device Authorization Grant

    New integrations and changes in this release:

    • HTTPX OAuth 1.0 and OAuth 2.0 clients in both sync and async way
    • Starlette OAuth 1.0 and OAuth 2.0 client registry
    • The experimental authlib.client.aiohttp has been removed

    Bug fixes and enhancements in this release:

    • Add custom client authentication methods for framework integrations.
    • Refresh token automatically for client_credentials grant type.
    • Enhancements on JOSE, specifying alg values easily for JWS and JWE.
    • Add PKCE into requests OAuth2Session and HTTPX OAuth2Client.

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/Jeclj

    Source code(tar.gz)
    Source code(zip)
  • v0.12.1(Sep 12, 2019)

    This is a bug fix version. Here are the fixes:

    1. ensure client.get_allowed_scope on every grant types
    2. add request.client before validate_requested_scope
    Source code(tar.gz)
    Source code(zip)
  • v0.12(Sep 3, 2019)

    Released on Sep 3, 2019.

    Breaking Change: Authlib Grant system has been redesigned. If you are creating OpenID Connect providers, please read the new documentation for OpenID Connect.

    Important Update: Django OAuth 2.0 server integration is ready now. You can create OAuth 2.0 provider and OpenID Connect 1.0 with Django framework.

    RFC implementations and updates in this release:

    • RFC6749: Fixed scope validation, omit the invalid scope
    • RFC7521: Added a common AssertionClient for the assertion framework
    • RFC7662: Added IntrospectionToken for introspection token endpoint
    • OpenID Connect Discover: Added discovery model based on RFC8414

    Refactor and bug fixes in this release:

    • Breaking Change: add RefreshTokenGrant.revoke_old_credential method
    • Rewrite lots of code for authlib.client, no breaking changes
    • Refactor OAuth2Request, use explicit query and form
    • Change requests to optional dependency
    • Add AsyncAssertionClient for aiohttp

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/fjPsV

    Code Changes: https://github.com/lepture/authlib/compare/v0.11...v0.12

    Source code(tar.gz)
    Source code(zip)
  • v0.11(Apr 6, 2019)

    BIG NEWS: Authlib has changed its open source license from AGPL to BSD.

    Important Changes: Authlib specs module has been split into jose, oauth1, oauth2, and oidc. Find how to solve the deprecate issues via https://git.io/fjvpt.

    RFC implementations and updates in this release:

    • RFC7518: Added A128GCMKW, A192GCMKW, A256GCMKW algorithms for JWE.
    • RFC5849: Removed draft-eaton-oauth-bodyhash-00 spec for OAuth 1.0.

    Small changes and bug fixes in this release:

    • Fixed missing scope on password and client_credentials grant types of OAuth2Session via issue#96.
    • Fixed Flask OAuth client cache detection viaissue#98.
    • Enabled ssl certificates for OAuth2Session via PR#100, thanks to pingz.
    • Fixed error response for invalid/expired refresh token via issue#112.
    • Fixed error handle for invalid redirect uri via issue#113.
    • Fixed error response redirect to fragment via issue#114.
    • Fixed non-compliant responses from RFC7009 via issue#119.

    Experiment Features: There is an experiment aiohttp client for OAuth1 and OAuth2 in authlib.client.aiohttp.

    Code Changes: https://github.com/lepture/authlib/compare/v0.10...v0.11

    Source code(tar.gz)
    Source code(zip)
  • v0.10(Oct 12, 2018)

    The most important change in this version is grant extension system. When registering a grant, developers can pass extensions to the grant:

    authorization_server.register_grant(GrantClass, [extension])
    

    Find Flask Grant Extensions implementation.

    RFC implementations and updates in this release:

    • RFC8414: OAuth 2.0 Authorization Server Metadata
    • RFC7636: make CodeChallenge a grant extension
    • OIDC: make OpenIDCode a grant extension

    Besides that, there are other improvements:

    • Export save_authorize_state method on Flask and Django client
    • Add fetch_token to Django OAuth client
    • Add scope operator for @require_oauth Multiple Scopes
    • Fix two OAuth clients in the same Flask route PR#85

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/fAmW1

    Code Changes: https://github.com/lepture/authlib/compare/v0.9...v0.10

    Source code(tar.gz)
    Source code(zip)
  • v0.9(Aug 12, 2018)

    There is no big break changes in this version. The very great improvement is adding JWE support. But the JWA parts of JWE are not finished yet, use with caution.

    RFC implementations in this release:

    Other Changes:

    • Fixed the lazy initialization of Flask OAuth 2.0 provider.
    • Deprecated authlib.client.apps from v0.7 has been dropped.

    Documentation: https://docs.authlib.org/en/v0.9/

    Code Changes: https://github.com/lepture/authlib/compare/v0.8...v0.9

    Source code(tar.gz)
    Source code(zip)
  • v0.8(Jun 17, 2018)

    Authlib has tried to introduce Django OAuth server implementation in this version. It turns out that it is not that easy. In this version, only Django OAuth 1.0 server is provided.

    As always, there are also RFC features added in this release, here is what's in version 0.8:

    Improvement in this release:

    • A new redesigned error system. All errors are subclasses of a AuthlibBaseError.
    • I18N support for error descriptions.
    • Separate AuthorizationCodeMixin in authlib.flask.oauth2.sqla via issue#57.
    • Add context information when generate token via issue#58.
    • Improve JWT key handles, auto load JWK and JWK set.
    • Add require_oauth.acquire with statement, get example on Flask OAuth 2.0 Server.

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/vhL75

    Code Changes: https://github.com/lepture/authlib/compare/v0.7...v0.8

    Source code(tar.gz)
    Source code(zip)
  • v0.7(Apr 28, 2018)

    Authlib has changed its license from LGPL to AGPL. This is not a huge release like v0.6, but it still contains some deprecate changes, the good news is they are compatible, they won’t break your project. Authlib can’t go further without these deprecate changes.

    As always, Authlib is adding specification implementations. Here is what’s new in version 0.7:

    Besides that, there are more changes:

    • Add overwrite parameter for framework integrations clients.
    • Add response_mode=query for OpenID Connect implicit and hybrid flow.
    • Bug fix and documentation fix via issue#42, issue#43.
    • Dropping authlib.client.apps. Use loginpass instead.

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/vpCH5

    Code Changes: https://github.com/lepture/authlib/compare/v0.6...v0.7

    Source code(tar.gz)
    Source code(zip)
  • v0.6(Mar 20, 2018)

    From alpha to beta. This is a huge release with lots of deprecating changes and some breaking changes. And finally, OpenID Connect server is supported by now, because Authlib has added these specifications:

    • RFC7515: JSON Web Signature (JWS)
    • RFC7517: JSON Web Key (JWK)
    • RFC7518: JSON Web Algorithms (JWA)
    • RFC7519: JSON Web Token (JWT)

    The specifications are not completed yet, but they are ready to use. The missing RFC7516 (JWE) is going to be implemented in next version. Open ID Connect 1.0 is added with:

    Besides that, there are more changes:

    • Implementation of RFC7662: OAuth 2.0 Token Introspection via #36.
    • Use the token_endpoint_auth_method concept defined in RFC7591.
    • Signal feature for Flask integration of OAuth 2.0 server.
    • Bug fixes for OAuth client parts, thanks for the instruction by Lukas Schink.

    Breaking Changes:

    1. the columns in authlib.flask.oauth2.sqla has been changed a lot. If you are using it, you need to upgrade your database.
    2. use register_token_validator on ResourceProtector.
    3. authlib.client.oauth1.OAuth1 has been renamed to authlib.client.oauth1.OAuth1Auth.

    Deprecate Changes: find how to solve the deprecate issues via https://git.io/vAAUK

    Code Changes: https://github.com/lepture/authlib/compare/v0.5.1...v0.6

    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Feb 11, 2018)

  • v0.5(Feb 11, 2018)

    This version breaks a lot of things. There are many redesigns in order to get a better stable API. It is still in Alpha stage, with these breaking changes, I hope Authlib will go into Beta in the next version.

    • Added register_error_uri() and its Flask integration.
    • OAuth2Session supports more grant types.
    • Deprecate built-in cache. Read more on issue#23.
    • Redesigned OAuth 1 Flask server. Read the docs Flask OAuth 1 Server.
    • Deprecate client_model. Read more on issue#27.
    • Breaking change on AuthorizationCodeGrant.create_authorization_code, last parameter is changed to an OAuth2Request instance.
    • Rename callback_uri to redirect_uri in client.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Feb 1, 2018)

  • v0.4(Jan 31, 2018)

    This version is released when people are enjoying the super blue blood moon. That's why this version is called Tsukino. The full name would be Tsukino Usagi.

    This is a feature releasing for OAuth 1 server. Things are not settled yet, there will still be breaking changes in the future. Some of the breaking changes are compatible with deprecated messages, a few are not. I’ll keep the deprecated message for 2 versions. Here is the main features:

    • RFC5847, OAuth 1 client and server
    • Flask implementation of OAuth 1 authorization server and resource protector.
    • Mixin of SQLAlchemy models for easy integration with OAuth 1.

    In version 0.4, there is also several bug fixes. Thanks for the early contributors.

    • Allow Flask OAuth register fetch_token and update_token.
    • Bug fix for OAuthClient when refresh_token_params is None via PR#14.
    • Don’t pass everything in request args for Flask OAuth client via issue#16.
    • Bug fix for IDToken.validate_exp via issue#17.
    Source code(tar.gz)
    Source code(zip)
  • v0.3(Dec 24, 2017)

    This is a feature releasing for OAuth 2 server. Since this is the first release of the server implementation, you would expect that there are bugs, security vulnerabilities, and uncertainties. Try it bravely.

    • RFC6749, all grant types, refresh token, authorization server.
    • RFC6750, bearer token creation and validation.
    • RFC7009, token revocation.
    • Flask implementation of authorization server and resource protector.
    • Mixin of SQLAlchemy models for easy integration.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Dec 6, 2017)

  • v0.2(Nov 29, 2017)

Owner
Hsiaoming Yang
This guy is too lazy to introduce himself.
Hsiaoming Yang
A Python library for OAuth 1.0/a, 2.0, and Ofly.

Rauth A simple Python OAuth 1.0/a, OAuth 2.0, and Ofly consumer library built on top of Requests. Features Supports OAuth 1.0/a, 2.0 and Ofly Service

litl 1.6k Dec 08, 2022
Imia is an authentication library for Starlette and FastAPI (python 3.8+).

Imia Imia (belarussian for "a name") is an authentication library for Starlette and FastAPI (python 3.8+). Production status The library is considered

Alex Oleshkevich 91 Nov 24, 2022
Strong, Simple, and Precise security for Flask APIs (using jwt)

flask-praetorian Strong, Simple, and Precise security for Flask APIs API security should be strong, simple, and precise like a Roman Legionary. This p

Tucker Beck 321 Dec 18, 2022
API-key based security utilities for FastAPI, focused on simplicity of use

FastAPI simple security API key based security package for FastAPI, focused on simplicity of use: Full functionality out of the box, no configuration

Tolki 154 Jan 03, 2023
Simple yet powerful authorization / authentication client library for Python web applications.

Authomatic Authomatic is a framework agnostic library for Python web applications with a minimalistic but powerful interface which simplifies authenti

1k Dec 28, 2022
Phishing Abusing Microsoft 365 OAuth Authorization Flow

Microsoft365_devicePhish Abusing Microsoft 365 OAuth Authorization Flow for Phishing Attack This is a simple proof-of-concept script that allows an at

bigb0ss 11 Dec 11, 2022
row level security for FastAPI framework

Row Level Permissions for FastAPI While trying out the excellent FastApi framework there was one peace missing for me: an easy, declarative way to def

Holger Frey 315 Dec 25, 2022
Skit-auth - Authorization for skit.ai's platform

skit-auth This is a simple authentication library for Skit's platform. Provides

Skit 3 Jan 08, 2022
An open source Flask extension that provides JWT support (with batteries included)!

Flask-JWT-Extended Features Flask-JWT-Extended not only adds support for using JSON Web Tokens (JWT) to Flask for protecting views, but also many help

Landon Gilbert-Bland 1.4k Jan 04, 2023
Google Auth Python Library

Google Auth Python Library This library simplifies using Google's various server-to-server authentication mechanisms to access Google APIs. Installing

Google APIs 598 Jan 07, 2023
Abusing Microsoft 365 OAuth Authorization Flow for Phishing Attack

Microsoft365_devicePhish Abusing Microsoft 365 OAuth Authorization Flow for Phishing Attack This is a simple proof-of-concept script that allows an at

Optiv Security 76 Jan 02, 2023
Alisue 299 Dec 06, 2022
Storefront - A store App developed using Django, RESTFul API, JWT

Storefront A store App developed using Django, RESTFul API, JWT. SQLite has been

Muhammad Algshy 1 Jan 07, 2022
User-related REST API based on the awesome Django REST Framework

Django REST Registration User registration REST API, based on Django REST Framework. Documentation Full documentation for the project is available at

Andrzej Pragacz 399 Jan 03, 2023
Flask App With Login

Flask App With Login by FranciscoCharles Este projeto basico é o resultado do estudos de algumas funcionalidades do micro framework Flask do Python. O

Charles 3 Nov 14, 2021
This project is an open-source project which I made due to sharing my experience around the Python programming language.

django-tutorial This project is an open-source project which I made due to sharing my experience around the Django framework. What is Django? Django i

MohammadMasoumi 6 May 12, 2022
Python's simple login system concept - Advanced level

Simple login system with Python - For beginners Creating a simple login system using python for beginners this repository aims to provide a simple ove

Low_Scarlet 1 Dec 13, 2021
A JSON Web Token authentication plugin for the Django REST Framework.

Simple JWT Abstract Simple JWT is a JSON Web Token authentication plugin for the Django REST Framework. For full documentation, visit django-rest-fram

Jazzband 3.2k Dec 28, 2022
This is a Token tool that gives you many options to harm the account.

Trabis-Token-Tool This is a Token tool that gives you many options to harm the account. Utilities With this tools you can do things as : ·Delete all t

Steven 2 Feb 13, 2022
Django x Elasticsearch Templates

Django x Elasticsearch Requirements Python 3.7 Django = 3 Elasticsearch 7.15 Setup Elasticsearch Install via brew Install brew tap elastic/tap brew

Aji Pratama 0 May 22, 2022