# index.html.md # Welcome to Python Social Auth’s documentation! Python Social Auth aims to be an easy-to-setup social authentication and authorization mechanism for Python projects supporting protocols like OAuth (1 and 2), OpenID and others. The initial codebase is derived from [django-social-auth](http://github.com/omab/django-social-auth) with the idea of generalizing the process to suit the different frameworks around, providing the needed tools to bring support to new frameworks. [django-social-auth](http://github.com/omab/django-social-auth) itself was a product of modified code from [django-twitter-oauth](https://github.com/henriklied/django-twitter-oauth) and [django-openid-auth](https://launchpad.net/django-openid-auth) projects. The project is now split into smaller modules to isolate and reduce responsibilities and improve reusability. Code and other contributions are welcome. The code is hosted on [GitHub](https://github.com/python-social-auth/). For AI assistants, the [documentation index](llms.txt) links to Markdown versions of the pages. The [complete documentation](llms-full.txt) is also available as a single Markdown file. # api/index.html.md # API Reference This reference covers the main extension points provided by `social-auth-core`. The generated pages include links to the corresponding source code. ## Authentication backends ### *class* social_core.backends.base.BaseAuth(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) A authentication backend that authenticates the user based on the provider response #### EXTRA_DATA *: [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str) | [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str), [bool](https://docs.python.org/3/builtins/functions.html#bool)]] | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### GET_ALL_EXTRA_DATA *= False* #### ID_KEY *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* *= ''* #### REQUIRES_EMAIL_VALIDATION *= False* #### REQUIRES_USER_ID *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* *= False* #### SEND_USER_AGENT *= True* #### auth_allowed(response, details) Return True if the user should be allowed to authenticate, by default check if email is whitelisted (if there’s a whitelist) #### auth_complete(\*args, \*\*kwargs) → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) Completes login process, must return user instance #### auth_extra_arguments() → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return extra arguments needed on auth process. Configured AUTH_EXTRA_ARGUMENTS are not overridden by request data by default. Set AUTH_EXTRA_ARGUMENTS_OVERRIDE_ALLOWLIST to an iterable of configured extra-argument keys that may be replaced by matching request data values. #### auth_html() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Must return login HTML content returned by provider #### auth_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Must return redirect URL to auth provider #### authenticate(\*args, \*\*kwargs) → [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) Authenticate user using social credentials Authentication is made if this is the correct backend, backend verification is made by kwargs inspection for current backend name presence. #### complete(\*args, \*\*kwargs) → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) #### continue_pipeline(partial: [PartialMixin](api/index.html.md#social_core.storage.PartialMixin)) → [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) Continue previous halted pipeline #### disconnect(\*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) #### extra_data(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None), uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), response: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any], details: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any], pipeline_kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any]) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any] Return default extra data to store in extra_data field #### get_json(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), method: Literal['GET', 'POST', 'DELETE'] = 'GET', headers: Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None, data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, json: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, auth: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | AuthBase | [None](https://docs.python.org/3/builtins/constants.html#None) = None, params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, timeout: [float](https://docs.python.org/3/builtins/functions.html#float) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[Any, Any] #### get_key_and_secret() → [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return tuple with Consumer Key and Consumer Secret for current service provider. Must return (key, secret), order *must* be respected. #### get_key_and_secret_basic_auth() → [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes) Generate HTTP Basic Authentication header value from KEY and SECRET. Returns: : Basic authentication value in the format b”Basic ” #### get_querystring(url, \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### get_user(user_id) Return user with given ID from the User model used by this backend. This is called by django.contrib.auth.middleware. #### get_user_details(response) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] Return user details in a known internal structure. The returned dictionary can contain: `username` : Username, if any. `email` : User email, if any. `fullname` : User full name, if any. `first_name` : User first name, if any. `last_name` : User last name, if any. #### get_user_id(details, response) Return a unique ID for the current user, by default from server response or details. #### get_user_id_from_sources(\*sources: Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any] | [None](https://docs.python.org/3/builtins/constants.html#None), id_key: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Return the selected user ID from mappings or fail clearly. Sources are searched in order for the configured or explicitly passed ID key. Missing, `None`, and empty-string values are rejected. #### get_user_names(fullname='', first_name='', last_name='') #### id_key() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return the ID_KEY to use for this backend, checking settings first. #### log_debug(message, \*args) → [None](https://docs.python.org/3/builtins/constants.html#None) #### log_warning(message, \*args) → [None](https://docs.python.org/3/builtins/constants.html#None) #### name *= ''* #### pipeline(pipeline, pipeline_index: [int](https://docs.python.org/3/builtins/functions.html#int) = 0, \*args, \*\*kwargs) → [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) #### prepare_auth(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [None](https://docs.python.org/3/builtins/constants.html#None) Prepare backend-specific validation or state before authentication starts. #### process_error(data) → [None](https://docs.python.org/3/builtins/constants.html#None) Hook to process provider response errors. Default implementation is a no-op. Backends that can detect provider-specific error payloads should override this method and raise an appropriate exception when needed. #### request(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), , method: Literal['GET', 'POST', 'DELETE'] = 'GET', headers: Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None, data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, json: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, auth: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | AuthBase | [None](https://docs.python.org/3/builtins/constants.html#None) = None, params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, timeout: [float](https://docs.python.org/3/builtins/functions.html#float) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → Response #### run_pipeline(pipeline: [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)], pipeline_index=0, \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) #### setting(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), default=None) Return setting value from strategy #### start() → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) #### supports_inactive_user *= False* #### uses_redirect() → [bool](https://docs.python.org/3/builtins/functions.html#bool) Return True if this provider uses redirect url method, otherwise return false. #### validate_partial_pipeline(partial: [PartialMixin](api/index.html.md#social_core.storage.PartialMixin), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [None](https://docs.python.org/3/builtins/constants.html#None) Validate backend-specific requirements before resuming a pipeline. ### *class* social_core.backends.oauth.BaseOAuth1(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`OAuthAuth`](api/index.html.md#social_core.backends.oauth.OAuthAuth) Consumer based mechanism OAuth authentication, fill the needed parameters to communicate properly with authentication service. URLs settings: : REQUEST_TOKEN_URL Request token URL #### OAUTH_TOKEN_PARAMETER_NAME *= 'oauth_token'* #### REDIRECT_URI_PARAMETER_NAME *= 'redirect_uri'* #### REQUEST_TOKEN_METHOD *: Literal['GET', 'POST']* *= 'GET'* #### REQUEST_TOKEN_URL *= ''* #### UNATHORIZED_TOKEN_SUFIX *= 'unauthorized_token_name'* #### access_token(token: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return request for access token value #### auth_complete(\*args, \*\*kwargs) Return user, might be logged in #### auth_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return redirect url #### do_auth(access_token, \*args, \*\*kwargs) Finish the auth process once the access_token was retrieved #### get_unauthorized_token() #### oauth_auth(token: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, oauth_verifier=None, signature_type='AUTH_HEADER') #### oauth_authorization_request(token) Generate OAuth request to authorize token. #### oauth_request(token: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict), url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), params=None, method: Literal['GET', 'POST'] = 'GET') → Response Generate OAuth request, setups callback url #### process_error(data) → [None](https://docs.python.org/3/builtins/constants.html#None) Hook to process provider response errors. Default implementation is a no-op. Backends that can detect provider-specific error payloads should override this method and raise an appropriate exception when needed. #### request_token_extra_arguments() → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return extra arguments needed on request-token process #### set_unauthorized_token() #### unauthorized_token() Return request for unauthorized token (first stage) #### user_data(access_token: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict), \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) Loads user data from service. Implement in subclass ### *class* social_core.backends.oauth.BaseOAuth2(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`OAuthAuth`](api/index.html.md#social_core.backends.oauth.OAuthAuth) Base class for OAuth2 providers. OAuth2 details at: : [https://datatracker.ietf.org/doc/html/rfc6749](https://datatracker.ietf.org/doc/html/rfc6749) #### REDIRECT_STATE *= True* #### REFRESH_TOKEN_METHOD *: Literal['GET', 'POST', 'DELETE']* *= 'POST'* #### REFRESH_TOKEN_URL *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### RESPONSE_TYPE *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= 'code'* #### STATE_PARAMETER *= True* #### USE_BASIC_AUTH *= False* #### auth_complete(\*args, \*\*kwargs) Completes login process, must return user instance #### auth_complete_credentials() #### auth_complete_params(state=None) #### auth_headers() → Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)] #### auth_params(state: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### auth_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return redirect url #### do_auth(access_token, \*args, \*\*kwargs) Finish the auth process once the access_token was retrieved #### extra_data(user, uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), response: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], details: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], pipeline_kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] Return access_token, token_type, and extra defined names to store in extra_data field #### process_error(data) → [None](https://docs.python.org/3/builtins/constants.html#None) Hook to process provider response errors. Default implementation is a no-op. Backends that can detect provider-specific error payloads should override this method and raise an appropriate exception when needed. #### process_refresh_token_response(response, \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) #### refresh_token(token: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) #### refresh_token_auth() → AuthBase | [None](https://docs.python.org/3/builtins/constants.html#None) #### refresh_token_params(token: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### refresh_token_url() #### request_access_token(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), method: Literal['GET', 'POST', 'DELETE'] = 'GET', headers: Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None, data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, json: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, auth: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | AuthBase | [None](https://docs.python.org/3/builtins/constants.html#None) = None, params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[Any, Any] #### use_basic_auth() → [bool](https://docs.python.org/3/builtins/functions.html#bool) #### user_data(access_token: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) Loads user data from service. Implement in subclass ### *class* social_core.backends.oauth.BaseOAuth2PKCE(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`BaseOAuth2`](api/index.html.md#social_core.backends.oauth.BaseOAuth2) Base class for providers using OAuth2 with Proof Key for Code Exchange (PKCE). OAuth2 details at: : [https://datatracker.ietf.org/doc/html/rfc6749](https://datatracker.ietf.org/doc/html/rfc6749) PKCE details at: : [https://datatracker.ietf.org/doc/html/rfc7636](https://datatracker.ietf.org/doc/html/rfc7636) #### DEFAULT_USE_PKCE *= True* #### PKCE_DEFAULT_CODE_CHALLENGE_METHOD *= 'S256'* #### PKCE_DEFAULT_CODE_VERIFIER_LENGTH *= 43* #### auth_complete_params(state=None) #### auth_params(state=None) #### create_code_verifier() #### generate_code_challenge(code_verifier, challenge_method) #### get_code_verifier() ### *class* social_core.backends.oauth.OAuthAuth(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`BaseAuth`](api/index.html.md#social_core.backends.base.BaseAuth) OAuth authentication backend base class. Settings will be inspected to get more values names that should be stored on extra_data field. The setting name is created following the pattern SOCIAL_AUTH__EXTRA_DATA. access_token is always stored. URLs settings: : AUTHORIZATION_URL Authorization service url ACCESS_TOKEN_URL Access token URL #### ACCESS_TOKEN_METHOD *: Literal['GET', 'POST']* *= 'POST'* #### ACCESS_TOKEN_PAYLOAD *: Literal['form', 'json']* *= 'form'* #### ACCESS_TOKEN_URL *= ''* #### AUTHORIZATION_URL *= ''* #### DEFAULT_SCOPE *: [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### ID_KEY *= 'id'* #### REDIRECT_STATE *= False* #### REVOKE_TOKEN_METHOD *: Literal['GET', 'POST', 'DELETE']* *= 'POST'* #### REVOKE_TOKEN_URL *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* *= ''* #### SCOPE_PARAMETER_NAME *= 'scope'* #### SCOPE_SEPARATOR *= ' '* #### STATE_PARAMETER *= False* #### access_token_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### authorization_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### extra_data(user, uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), response: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], details: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], pipeline_kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] Return access_token and extra defined names to store in extra_data field #### get_access_token_url_format() → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### get_authorization_url_format() → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### get_or_create_state() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) #### get_redirect_uri(state: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Build redirect with redirect_state parameter. #### get_request_state() #### get_scope() → [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return list with needed access scope #### get_scope_argument() #### get_session_state() #### process_revoke_token_response(response) #### revoke_token(token, uid) #### revoke_token_headers(token, uid) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] #### revoke_token_params(token, uid) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] #### revoke_token_url(token, uid) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### state_token() Generate csrf token to include as state parameter. #### user_data(access_token, \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) Loads user data from service. Implement in subclass #### validate_state() Validate state value. Raises exception on error, returns state value if valid. ### *class* social_core.backends.open_id.OpenIdAuth(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`BaseAuth`](api/index.html.md#social_core.backends.base.BaseAuth) Generic OpenID authentication backend #### URL *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### USERNAME_KEY *= 'username'* #### auth_complete(\*args, \*\*kwargs) Complete auth process #### auth_html() Return auth HTML returned by service #### auth_url() Return auth URL returned by service #### consumer() Create an OpenID Consumer object for the given Django request. #### continue_pipeline(partial) Continue previous halted pipeline #### create_consumer(store=None) #### extra_data(user, uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), response: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], details: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], pipeline_kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] Return defined extra data names to store in extra_data field. Settings will be inspected to get more values names that should be stored on extra_data field. Setting name is created from current backend name (all uppercase) plus \_SREG_EXTRA_DATA and \_AX_EXTRA_DATA because values can be returned by SimpleRegistration or AttributeExchange schemas. Both list must be a value name and an alias mapping similar to SREG_ATTR, OLD_AX_ATTRS or AX_SCHEMA_ATTRS #### get_ax_attributes() → [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)]] #### get_consumer_store() → OpenIdStore | [None](https://docs.python.org/3/builtins/constants.html#None) #### get_return_to() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### get_sreg_attributes() #### get_user_details(response) Return user details from an OpenID request #### get_user_id(details, response) Return the protocol-defined identity URL provided by the service. OpenID identity is asserted as a URL rather than a response mapping field, so the configurable ID_KEY does not apply to this backend. #### name *= 'openid'* #### openid_request(params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Return openid request #### openid_url() Return service provider URL. This base class is generic accepting a POST parameter that specifies provider URL. #### process_error(data) → [None](https://docs.python.org/3/builtins/constants.html#None) Hook to process provider response errors. Default implementation is a no-op. Backends that can detect provider-specific error payloads should override this method and raise an appropriate exception when needed. #### setup_request(params=None) Setup request #### trust_root() Return trust-root option #### uses_redirect() Return true if openid request will be handled with redirect or HTML content will be returned. #### values_from_response(response, sreg_names=None, ax_names=None) Return values from SimpleRegistration response or AttributeExchange response if present. @sreg_names and @ax_names must be a list of name and aliases for such name. The alias will be used as mapping key. ### *class* social_core.backends.open_id_connect.OpenIdConnectAssociation(handle, secret='', issued=0, lifetime=0, assoc_type='') Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) Use Association model to save the nonce by force. ### *class* social_core.backends.open_id_connect.OpenIdConnectAuth(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`BaseOAuth2PKCE`](api/index.html.md#social_core.backends.oauth.BaseOAuth2PKCE) Base class for Open ID Connect backends. Currently only the code response type is supported. It can also be directly instantiated as a generic OIDC backend. To use it you will need to set at minimum: SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = ‘[https://](https://)…..’ # endpoint without /.well-known/openid-configuration SOCIAL_AUTH_OIDC_KEY = ‘’ SOCIAL_AUTH_OIDC_SECRET = ‘’ SOCIAL_AUTH_OIDC_USE_PKCE = True # optional, enables PKCE for this backend #### ACCESS_TOKEN_URL *= ''* #### ACR_VALUES *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### AUTHORIZATION_URL *= ''* #### CUSTOM_AT_HASH_ALGO *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### DEFAULT_SCOPE *= ['openid', 'profile', 'email']* #### DEFAULT_USE_PKCE *= False* #### DISPLAY *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### EMAIL_KEY *= 'email'* #### EXTRA_DATA *= ['id_token', 'refresh_token', ('sub', 'id')]* #### FIRST_NAME_KEY *= 'given_name'* #### FULLNAME_KEY *= 'name'* #### ID_KEY *= 'sub'* #### ID_TOKEN_HINT *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### ID_TOKEN_ISSUER *= ''* #### ID_TOKEN_MAX_AGE *= 600* #### JWKS_URI *= ''* #### JWT_ALGORITHMS *= ['RS256']* #### JWT_DECODE_OPTIONS *: Options* *= {}* #### JWT_LEEWAY *: [float](https://docs.python.org/3/builtins/functions.html#float)* *= 1.0* #### LAST_NAME_KEY *= 'family_name'* #### LOGIN_HINT *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### MAX_AGE *: [int](https://docs.python.org/3/builtins/functions.html#int) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### OIDC_ENDPOINT *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### PKCE_DEFAULT_CODE_CHALLENGE_METHOD *= 'S256'* #### PROMPT *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### REDIRECT_STATE *= False* #### REVOKE_TOKEN_METHOD *: Literal['GET', 'POST', 'DELETE']* *= 'GET'* #### REVOKE_TOKEN_URL *= ''* #### TOKEN_ENDPOINT_AUTH_METHOD *= ''* #### UI_LOCALES *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### USERINFO_URL *= ''* #### USERNAME_KEY *= 'preferred_username'* #### VALIDATE_AT_HASH *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* *= True* #### access_token_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### auth_params(state=None) Return extra arguments needed on auth process. #### authorization_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### *static* calc_at_hash(access_token, algorithm, custom_at_hash_algo: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Calculates “at_hash” claim which is not done by pyjwt. Custom “at_hash” algorithm is used for non-standard token. See [https://pyjwt.readthedocs.io/en/stable/usage.html#oidc-login-flow](https://pyjwt.readthedocs.io/en/stable/usage.html#oidc-login-flow) See [https://github.com/python-social-auth/social-core/issues/1306](https://github.com/python-social-auth/social-core/issues/1306) #### decode_and_validate_id_token(id_token, access_token) Validate an ID token’s signature and self-contained claims. #### extra_data(user, uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), response: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], details: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], pipeline_kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] Return access_token, token_type, and extra defined names to store in extra_data field #### find_valid_key(id_token) #### get_and_store_nonce(url, state) #### get_jwks_keys(\*args, \*\*kwargs) #### get_nonce(nonce) #### get_remote_jwks_keys() #### get_setting_config(setting_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), oidc_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), default: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### get_user_details(response) Return user details from the UserInfo response or ID token. #### get_user_id(details, response) Return a unique ID for the current user, by default from server response or details. #### *static* id_token_audiences(audience) → [set](https://docs.python.org/3/builtins/stdtypes.html#set)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### id_token_issuer() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### jwks_uri() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### name *= 'oidc'* #### oidc_config(\*args, \*\*kwargs) #### oidc_endpoint() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### process_refresh_token_response(response, \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) #### remove_nonce(nonce_id) → [None](https://docs.python.org/3/builtins/constants.html#None) #### request_access_token(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), method: Literal['GET', 'POST', 'DELETE'] = 'GET', headers: Mapping[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None, data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, json: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, auth: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | AuthBase | [None](https://docs.python.org/3/builtins/constants.html#None) = None, params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[Any, Any] Retrieve the access token. Also, validate the id_token and store it (temporarily). #### revoke_token_url(token, uid) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### use_basic_auth() → [bool](https://docs.python.org/3/builtins/functions.html#bool) #### user_data(access_token: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) Loads user data from service. Implement in subclass #### userinfo_url() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### validate_and_return_id_token(id_token, access_token) Validates the id_token according to the steps at [http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation](http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation). #### validate_and_return_refresh_id_token(id_token, access_token) Validate an ID token returned by a refresh request. #### validate_at_hash(claims, access_token, key) Validate the ‘at_hash’ claim according to OpenID Connect specs. See: [https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken](https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken) #### validate_authorized_party(claims, client_id: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [None](https://docs.python.org/3/builtins/constants.html#None) Validate the client authorized to use the ID token. #### validate_claims(id_token) → [None](https://docs.python.org/3/builtins/constants.html#None) #### validate_refresh_id_token_claims(previous, current) → [None](https://docs.python.org/3/builtins/constants.html#None) Validate identity continuity for an ID token refresh. #### validate_required_id_token_claims(claims) → [None](https://docs.python.org/3/builtins/constants.html#None) Validate claims required in every ID token. #### validate_temporal_claims(id_token) → [None](https://docs.python.org/3/builtins/constants.html#None) #### validate_userinfo_sub(userinfo: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None)) → [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) Validate that UserInfo belongs to the validated ID token subject. ## Pipeline ### social_core.pipeline.social_auth.associate_by_email(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) Associate current auth with a user with the same email address in the DB. This pipeline entry is not 100% secure unless you know that the providers enabled enforce email verification on their side, otherwise a user can attempt to take over another user account by using the same (not validated) email address on some provider. This pipeline entry is disabled by default. ### social_core.pipeline.social_auth.associate_user(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), uid, user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, social=None, \*args, \*\*kwargs) ### social_core.pipeline.social_auth.auth_allowed(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, response, \*args, \*\*kwargs) → [None](https://docs.python.org/3/builtins/constants.html#None) ### social_core.pipeline.social_auth.load_extra_data(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, response, uid, user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) → [None](https://docs.python.org/3/builtins/constants.html#None) ### social_core.pipeline.social_auth.social_details(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, response, \*args, \*\*kwargs) ### social_core.pipeline.social_auth.social_uid(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, response, \*args, \*\*kwargs) ### social_core.pipeline.social_auth.social_user(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), uid, user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) ### social_core.pipeline.user.create_user(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy), details, backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) ### social_core.pipeline.user.get_username(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy), details, backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) ### social_core.pipeline.user.user_details(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy), details, backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) | [None](https://docs.python.org/3/builtins/constants.html#None), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) → [None](https://docs.python.org/3/builtins/constants.html#None) Update user details using data from provider. ### social_core.pipeline.mail.mail_validation(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), details, is_new=False, \*args, \*\*kwargs) ## Framework integration ### *class* social_core.strategy.BaseStrategy(storage: [type](https://docs.python.org/3/builtins/functions.html#type)[[BaseStorage](api/index.html.md#social_core.storage.BaseStorage)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None, tpl: [type](https://docs.python.org/3/builtins/functions.html#type)[[BaseTemplateStrategy](api/index.html.md#social_core.strategy.BaseTemplateStrategy)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### ALLOWED_CHARS *= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'* #### DEFAULT_TEMPLATE_STRATEGY alias of [`BaseTemplateStrategy`](api/index.html.md#social_core.strategy.BaseTemplateStrategy) #### SESSION_SAVE_KEY *= 'psa_session_id'* #### absolute_uri(path: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### authenticate(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) → [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) Trigger the authentication mechanism tied to the current framework #### build_absolute_uri(path: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Build absolute URI with given (optional) path #### clean_authenticate_args(\*args, \*\*kwargs) Take authenticate arguments and return a “cleaned” version of them #### clean_partial_pipeline(token) → [None](https://docs.python.org/3/builtins/constants.html#None) #### create_user(\*args, \*\*kwargs) #### from_session_value(val) #### get_backend(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), redirect_uri: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*\*kwargs) → [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) Return a configured backend instance #### get_backend_class(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [type](https://docs.python.org/3/builtins/functions.html#type)[[BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth)] Return a configured backend class #### get_backends() → [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] Return configured backends #### get_disconnect_pipeline(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### get_language() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return current language #### get_pipeline(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] #### get_session_id() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) Return session ID to be used by restore_session. #### get_setting(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Return value for given setting name #### get_user(\*args, \*\*kwargs) #### html(content: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) Return HTTP response with given content #### openid_session_dict(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → OpenIdSessionWrapper #### openid_store() → OpenIdStore #### partial_load(token: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) | [None](https://docs.python.org/3/builtins/constants.html#None) #### partial_pipeline_external_resume_confirmation(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), partial: [PartialMixin](api/index.html.md#social_core.storage.PartialMixin), request_data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any]) → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) #### partial_pipeline_external_resume_confirmed(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), request_data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), Any]) → [bool](https://docs.python.org/3/builtins/functions.html#bool) #### random_string(length: [int](https://docs.python.org/3/builtins/functions.html#int) = 12, chars: [str](https://docs.python.org/3/builtins/stdtypes.html#str) = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### redirect(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) Return a response redirect to the given URL #### render_html(tpl: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, html: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, context: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Render given template or raw html with given context #### request_data(merge: [bool](https://docs.python.org/3/builtins/functions.html#bool) = True) Return current request data (POST or GET) #### request_get() Request GET data #### request_host() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return current host value #### request_is_secure() → [bool](https://docs.python.org/3/builtins/functions.html#bool) Is the request using HTTPS? #### request_path() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) path of the current request #### request_port() → [int](https://docs.python.org/3/builtins/functions.html#int) Port in use for this request #### request_post() Request POST data #### restore_session(session_id: [str](https://docs.python.org/3/builtins/stdtypes.html#str), kwargs: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [None](https://docs.python.org/3/builtins/constants.html#None) Restores session and updates kwargs to match it. This is only called if get_session_id returns a value. #### send_email_validation(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), email: [str](https://docs.python.org/3/builtins/stdtypes.html#str), partial_token: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [CodeMixin](api/index.html.md#social_core.storage.CodeMixin) #### session_get(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), default=None) Return session value for given key #### session_pop(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Pop session value for given key #### session_set(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), value) Set session value for given key #### session_setdefault(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), value) #### setting(name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), default=None, backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) #### *property* storage *: [type](https://docs.python.org/3/builtins/functions.html#type)[[BaseStorage](api/index.html.md#social_core.storage.BaseStorage)]* #### to_session_value(val) #### validate_email(email: [str](https://docs.python.org/3/builtins/stdtypes.html#str), code: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [bool](https://docs.python.org/3/builtins/functions.html#bool) ### *class* social_core.strategy.BaseTemplateStrategy(strategy) Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### render(tpl: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, html: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, context: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### render_string(html: [str](https://docs.python.org/3/builtins/stdtypes.html#str), context: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### render_template(tpl: [str](https://docs.python.org/3/builtins/stdtypes.html#str), context: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) ### *class* social_core.strategy.HttpResponseProtocol(\*args, \*\*kwargs) Bases: [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) #### *property* url *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* Models mixins for Social Auth ### *class* social_core.storage.AssociationMixin Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) OpenId account association #### assoc_type *= ''* #### *classmethod* get(server_url: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, handle: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Get an Association instance #### handle *= ''* #### issued *= 0* #### lifetime *= 0* #### *classmethod* oids(server_url, handle=None) #### *classmethod* openid_association(assoc) #### *classmethod* remove(ids_to_delete) Remove an Association instance #### secret *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)* *= ''* #### server_url *= ''* #### *classmethod* store(server_url, association) Create an Association instance ### *class* social_core.storage.BaseStorage Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### association alias of [`AssociationMixin`](api/index.html.md#social_core.storage.AssociationMixin) #### code alias of [`CodeMixin`](api/index.html.md#social_core.storage.CodeMixin) #### *classmethod* is_integrity_error(exception) → [bool](https://docs.python.org/3/builtins/functions.html#bool) Check if given exception flags an integrity error in the DB #### nonce alias of [`NonceMixin`](api/index.html.md#social_core.storage.NonceMixin) #### partial alias of [`PartialMixin`](api/index.html.md#social_core.storage.PartialMixin) #### user alias of [`UserMixin`](api/index.html.md#social_core.storage.UserMixin) ### *class* social_core.storage.CodeMixin Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### code *= ''* #### email *= ''* #### *classmethod* generate_code() #### *classmethod* get_code(code) #### *classmethod* make_code(email: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [CodeMixin](api/index.html.md#social_core.storage.CodeMixin) #### *abstractmethod* save() #### verified *= False* #### verify() → [None](https://docs.python.org/3/builtins/constants.html#None) ### *class* social_core.storage.NonceMixin Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) One use numbers #### *classmethod* delete(nonce) Delete a Nonce instance #### *classmethod* get(server_url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), salt: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Retrieve a Nonce instance #### salt *= ''* #### server_url *= ''* #### timestamp *= 0* #### *classmethod* use(server_url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), timestamp, salt: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Create a Nonce instance ### *class* social_core.storage.PartialMixin Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### *property* args #### backend *= ''* #### data *: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]* *= {}* #### *classmethod* destroy(token: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) #### extend_kwargs(values) → [None](https://docs.python.org/3/builtins/constants.html#None) #### *classmethod* generate_token() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) #### *property* kwargs #### *classmethod* load(token: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) | [None](https://docs.python.org/3/builtins/constants.html#None) #### next_step *: [int](https://docs.python.org/3/builtins/functions.html#int)* #### *classmethod* prepare(backend: [str](https://docs.python.org/3/builtins/stdtypes.html#str), next_step: [int](https://docs.python.org/3/builtins/functions.html#int), data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]) → [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) #### *abstractmethod* save() #### *classmethod* store(partial: [PartialMixin](api/index.html.md#social_core.storage.PartialMixin)) → [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) #### token *= ''* ### *class* social_core.storage.PipelineUserProtocol(\*args, \*\*kwargs) Bases: [`UserProtocol`](api/index.html.md#social_core.storage.UserProtocol), [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) #### is_new *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* #### social_user *: [UserMixin](api/index.html.md#social_core.storage.UserMixin) | [None](https://docs.python.org/3/builtins/constants.html#None)* ### *class* social_core.storage.UserMixin Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object) #### ACCESS_TOKEN_EXPIRED_THRESHOLD *= 5* #### *property* access_token *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* Return access_token stored in extra_data or None #### access_token_expired() Return true / false if access token is already expired #### *classmethod* allowed_to_disconnect(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol), backend_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), association_id=None) → [bool](https://docs.python.org/3/builtins/functions.html#bool) Return if it’s safe to disconnect the social account for the given user #### *classmethod* changed(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol)) → [None](https://docs.python.org/3/builtins/constants.html#None) The given user instance is ready to be saved #### *classmethod* clean_username(value: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Clean username removing any unsupported character #### *classmethod* create_social_auth(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol), uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str), provider: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Create a UserSocialAuth instance for given user #### *classmethod* create_user(\*args, \*\*kwargs) Create a user instance #### *classmethod* disconnect(entry) Disconnect the social account for the given user #### expiration_datetime() #### expiration_timedelta() → [timedelta](https://docs.python.org/3/library/datetime.html#datetime.timedelta) | [None](https://docs.python.org/3/builtins/constants.html#None) Return provider session live seconds. Returns a timedelta ready to use with session.set_expiry(). If provider returns a timestamp instead of session seconds to live, the timedelta is inferred from current time (using UTC timezone). Handles three types of expiration data: - expires_on: Always treated as absolute timestamp - expires_in: Always treated as relative seconds from auth_time - expires: Uses heuristic (>63072000 = 2 years) to distinguish timestamp vs relative #### extra_data *: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)]* #### get_access_token(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) Returns a valid access token. #### get_backend(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy)) → [type](https://docs.python.org/3/builtins/functions.html#type)[[BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth)] #### get_backend_instance(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy)) → [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth) | [None](https://docs.python.org/3/builtins/constants.html#None) #### *classmethod* get_social_auth(provider: [str](https://docs.python.org/3/builtins/stdtypes.html#str), uid: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Return UserSocialAuth for given provider and uid #### *classmethod* get_social_auth_for_user(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol), provider: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, id: [int](https://docs.python.org/3/builtins/functions.html#int) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) Return all the UserSocialAuth instances for given user #### *classmethod* get_user(pk) Return user instance for given id #### *classmethod* get_username(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Return the username for given user #### *classmethod* get_users_by_email(email: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Return users instances for given email address #### provider *= ''* #### refresh_token(strategy: [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy), \*args, \*\*kwargs) → [None](https://docs.python.org/3/builtins/constants.html#None) #### *abstractmethod* save() #### set_extra_data(extra_data: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [bool](https://docs.python.org/3/builtins/functions.html#bool) #### uid *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* #### user *: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol)* #### *classmethod* user_exists(\*args, \*\*kwargs) → [bool](https://docs.python.org/3/builtins/functions.html#bool) Return True/False if a User instance exists with the given arguments. Arguments are directly passed to filter() manager method. #### *classmethod* user_model() → [type](https://docs.python.org/3/builtins/functions.html#type)[[UserProtocol](api/index.html.md#social_core.storage.UserProtocol)] Return the user model #### *classmethod* username_max_length() → [int](https://docs.python.org/3/builtins/functions.html#int) Return the max length for username ### *class* social_core.storage.UserProtocol(\*args, \*\*kwargs) Bases: [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) #### *property* id *: [int](https://docs.python.org/3/builtins/functions.html#int)* #### *property* is_active *: [bool](https://docs.python.org/3/builtins/functions.html#bool) | Callable[[], [bool](https://docs.python.org/3/builtins/functions.html#bool)]* #### *property* is_authenticated *: [bool](https://docs.python.org/3/builtins/functions.html#bool) | Callable[[], [bool](https://docs.python.org/3/builtins/functions.html#bool)]* #### *property* username *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* ## Errors and utilities ### *exception* social_core.exceptions.AuthAlreadyAssociated(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) A different user has already associated the target social account ### *exception* social_core.exceptions.AuthCanceled(\*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Auth process was canceled by user. ### *exception* social_core.exceptions.AuthConnectionError(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Connection error duing authentication. ### *exception* social_core.exceptions.AuthException(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Auth process exception. ### *exception* social_core.exceptions.AuthFailed(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Auth process failed for some reason. ### *exception* social_core.exceptions.AuthForbidden(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Authentication for this user is forbidden ### *exception* social_core.exceptions.AuthInvalidParameter(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), parameter: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) Bases: [`AuthMissingParameter`](api/index.html.md#social_core.exceptions.AuthMissingParameter) Invalid value for parameter to start or complete the process. ### *exception* social_core.exceptions.AuthMissingParameter(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), parameter: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Missing parameter needed to start or complete the process. ### *exception* social_core.exceptions.AuthNotImplementedParameter(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), parameter: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) Bases: [`AuthMissingParameter`](api/index.html.md#social_core.exceptions.AuthMissingParameter) Optional parameter not implemented to start or complete the process. ### *exception* social_core.exceptions.AuthReauthenticationRequired(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth)) Bases: [`AuthTokenError`](api/index.html.md#social_core.exceptions.AuthTokenError) The stored authentication context cannot establish token continuity. ### *exception* social_core.exceptions.AuthStateForbidden(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) State parameter is incorrect. ### *exception* social_core.exceptions.AuthStateMissing(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) State parameter is incorrect. ### *exception* social_core.exceptions.AuthTokenError(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Auth token error. ### *exception* social_core.exceptions.AuthTokenRevoked(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) User revoked the access_token in the provider. ### *exception* social_core.exceptions.AuthUnknownError(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Unknown auth process error. ### *exception* social_core.exceptions.AuthUnreachableProvider(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) Cannot reach the provider ### *exception* social_core.exceptions.DefaultStrategyMissingError Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Default strategy is not configured. ### *exception* social_core.exceptions.InvalidEmail(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*args, \*\*kwargs) Bases: [`AuthException`](api/index.html.md#social_core.exceptions.AuthException) ### *exception* social_core.exceptions.InvalidExpiryValue(field_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), value: [object](https://docs.python.org/3/builtins/functions.html#object)) Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Invalid expiry value in extra_data. ### *exception* social_core.exceptions.MissingBackend(backend_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Bases: [`WrongBackend`](api/index.html.md#social_core.exceptions.WrongBackend) ### *exception* social_core.exceptions.NotAllowedToDisconnect Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) User is not allowed to disconnect it’s social account. ### *exception* social_core.exceptions.SocialAuthBaseException Bases: [`ValueError`](https://docs.python.org/3/builtins/exceptions.html#ValueError) Base class for pipeline exceptions. ### *exception* social_core.exceptions.SocialAuthImproperlyConfiguredError Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Raised when configuration is invalid. ### *exception* social_core.exceptions.StrategyMissingBackendError Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Strategy storage backend is not configured. ### *exception* social_core.exceptions.StrategyMissingFeatureError(strategy_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str), feature_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) Strategy does not support this. ### *exception* social_core.exceptions.WrongBackend(backend_name: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) Bases: [`SocialAuthBaseException`](api/index.html.md#social_core.exceptions.SocialAuthBaseException) ### *class* social_core.utils.PartialPipelineResult(partial: 'PartialMixin | None' = None, response: 'HttpResponseProtocol | None' = None, halt: 'bool' = False) #### halt *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* *= False* #### partial *: [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* #### response *: [HttpResponseProtocol](api/index.html.md#social_core.strategy.HttpResponseProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* ### *class* social_core.utils.PartialPipelineSelection(token: 'str | None' = None, owns_token: 'bool' = False, pending_resume: 'bool' = False) #### owns_token *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* *= False* #### pending_resume *: [bool](https://docs.python.org/3/builtins/functions.html#bool)* *= False* #### token *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)* *= None* ### social_core.utils.append_slash(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Make sure we append a slash at the end of the URL otherwise we have issues with urljoin Example: >>> urlparse.urljoin(’[http://www.example.com/api/v3](http://www.example.com/api/v3)’, ‘user/1/’) ‘[http://www.example.com/api/user/1/](http://www.example.com/api/user/1/)’ ### social_core.utils.build_absolute_uri(host_url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), path: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Build absolute URI with given (optional) path ### *class* social_core.utils.cache(ttl: [int](https://docs.python.org/3/builtins/functions.html#int)) Cache decorator that caches the return value of a method for a specified time. It maintains a cache per class and method arguments, so subclasses have a different cache entry for the same cached method. #### cache *: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[type](https://docs.python.org/3/builtins/functions.html#type), [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[Any](https://docs.python.org/3/library/typing.html#typing.Any), ...], [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [Any](https://docs.python.org/3/library/typing.html#typing.Any)], ...]], [Any](https://docs.python.org/3/library/typing.html#typing.Any)]* ### social_core.utils.constant_time_compare(val1: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes), val2: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [bytes](https://docs.python.org/3/builtins/stdtypes.html#bytes)) → [bool](https://docs.python.org/3/builtins/functions.html#bool) Compare two values and prevent timing attacks for cryptographic use. ### social_core.utils.drop_lists(value) ### social_core.utils.first(func, items) Return the first item in the list for what func returns True ### social_core.utils.get_allowed_redirect_schemes(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth)) → [set](https://docs.python.org/3/builtins/stdtypes.html#set)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] ### social_core.utils.get_querystring(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) ### social_core.utils.get_strategy(strategy: [str](https://docs.python.org/3/builtins/stdtypes.html#str), storage: [str](https://docs.python.org/3/builtins/stdtypes.html#str), \*args, \*\*kwargs) → [BaseStrategy](api/index.html.md#social_core.strategy.BaseStrategy) ### social_core.utils.handle_http_errors(func) ### social_core.utils.is_private_use_redirect(value: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None), allowed_schemes: Collection[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [bool](https://docs.python.org/3/builtins/functions.html#bool) Whether `value` uses a non-web scheme that has been explicitly allowed. URI construction helpers such as `build_absolute_uri` only preserve http and https, so callers must check this before turning a redirect candidate into an absolute URI. ### social_core.utils.is_url(value: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None), allowed_schemes: Collection[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [bool](https://docs.python.org/3/builtins/functions.html#bool) ### social_core.utils.module_member(name) ### social_core.utils.normalize_redirect_schemes(schemes: Collection[[str](https://docs.python.org/3/builtins/stdtypes.html#str)]) → [set](https://docs.python.org/3/builtins/stdtypes.html#set)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] URI schemes are case-insensitive, and urlparse lowercases them. ### social_core.utils.parse_qs(value) Like urlparse.parse_qs but transform list values to single items ### social_core.utils.partial_pipeline_data(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, partial_token: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) → [PartialMixin](api/index.html.md#social_core.storage.PartialMixin) | [None](https://docs.python.org/3/builtins/constants.html#None) ### social_core.utils.partial_pipeline_result(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, partial_token: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) = None, \*args, \*\*kwargs) → [PartialPipelineResult](api/index.html.md#social_core.utils.PartialPipelineResult) ### social_core.utils.sanitize_redirect(hosts: [list](https://docs.python.org/3/builtins/stdtypes.html#list)[[str](https://docs.python.org/3/builtins/stdtypes.html#str)], redirect_to: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | Any, allowed_schemes: Collection[[str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None) = None) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) Given a list of hostnames and an untrusted URL to redirect to, this method tests it to make sure it isn’t garbage/harmful and returns it, else returns None, similar as how’s it done on django.contrib.auth.views. `allowed_schemes` defaults to http and https. Deployments that need to hand control back to a native application can add a private-use URI scheme (RFC 8252) through the `ALLOWED_REDIRECT_SCHEMES` setting. ### social_core.utils.setting_name(\*names: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) ### social_core.utils.setting_url(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth), \*names: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None) ### social_core.utils.slugify(value) Converts to lowercase, removes non-word characters (alphanumerics and underscores) and converts spaces to hyphens. Also strips leading and trailing whitespace. ### social_core.utils.to_setting_name(\*names: [str](https://docs.python.org/3/builtins/stdtypes.html#str)) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) ### social_core.utils.url_add_parameters(url: [str](https://docs.python.org/3/builtins/stdtypes.html#str), params: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)] | [None](https://docs.python.org/3/builtins/constants.html#None), \_unquote_query: [bool](https://docs.python.org/3/builtins/functions.html#bool) = False) → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Adds parameters to URL, parameter will be repeated if already present ### social_core.utils.user_agent() → [str](https://docs.python.org/3/builtins/stdtypes.html#str) Builds a simple User-Agent string to send in requests ### social_core.utils.user_is_active(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None)) → [bool](https://docs.python.org/3/builtins/functions.html#bool) ### social_core.utils.user_is_authenticated(user: [UserProtocol](api/index.html.md#social_core.storage.UserProtocol) | [None](https://docs.python.org/3/builtins/constants.html#None)) → [bool](https://docs.python.org/3/builtins/functions.html#bool) ### social_core.utils.wrap_access_token_error(backend: [BaseAuth](api/index.html.md#social_core.backends.base.BaseAuth)) # backends/amazon.html.md # Amazon ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `amazon` | `social_core.backends.amazon.AmazonOAuth2` | Amazon implemented OAuth2 protocol for their authentication mechanism. To enable `python-social-auth` support follow this steps: 1. Go to [Amazon App Console](http://login.amazon.com/manageApps) and create an application. 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_AMAZON_KEY = '...' SOCIAL_AUTH_AMAZON_SECRET = '...' ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.amazon.AmazonOAuth2', ... ) ``` Further documentation at [Website Developer Guide](https://images-na.ssl-images-amazon.com/images/G/01/lwa/dev/docs/website-developer-guide._TTH_.pdf) and [Getting Started for Web](http://login.amazon.com/website). **Note:** This backend supports TLSv1 protocol since SSL will be deprecated : from May 25, 2015 # backends/angel.html.md # Angel List ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `angel` | `social_core.backends.angel.AngelOAuth2` | Angel uses OAuth v2 for Authentication. - Register a new application at the [Angel List API](https://angel.co/api/oauth/faq), and - fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_ANGEL_KEY = '' SOCIAL_AUTH_ANGEL_SECRET = '' ``` - extra scopes can be defined by using: ```default SOCIAL_AUTH_ANGEL_AUTH_EXTRA_ARGUMENTS = {'scope': 'email messages'} ``` **Note:** Angel List does not currently support returning `state` parameter used to validate the auth process. # backends/apple.html.md # AppleID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `apple-id` | `social_core.backends.apple.AppleIdAuth` | Apple ID implemented OAuth2 and OpenID Connect protocols for their authentication mechanism. To enable `python-social-auth` support follow this steps: 1. Go to [Apple Developer Portal](https://developer.apple.com/) and 1. [Create or select an existing App ID](https://help.apple.com/developer-account/?lang=en#/devde676e696) 2. [Create a Sign Certificate](https://help.apple.com/developer-account/?lang=en#/dev77c875b7e) 3. [Create a Services ID](https://help.apple.com/developer-account/?lang=en#/dev1c0e25352), activate “Sign In with Apple” and grant your “return URLs” 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_APPLE_ID_CLIENT = '...' # Your client_id com.application.your, aka "Service ID" SOCIAL_AUTH_APPLE_ID_TEAM = '...' # Your Team ID, ie K2232113 SOCIAL_AUTH_APPLE_ID_KEY = '...' # Your Key ID, ie Y2P99J3N81K SOCIAL_AUTH_APPLE_ID_SECRET = """ -----BEGIN PRIVATE KEY----- MIGTAgE..... -----END PRIVATE KEY-----""" SOCIAL_AUTH_APPLE_ID_SCOPE = ['email', 'name'] SOCIAL_AUTH_APPLE_ID_EMAIL_AS_USERNAME = True # If you want to use email as username ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.apple.AppleIdAuth', ... ) ``` Further documentation at [Website Developer Guide](https://developer.apple.com/documentation/signinwithapplerestapi/authenticating_users_with_sign_in_with_apple) and [Getting Started](https://developer.apple.com/sign-in-with-apple/get-started/). # backends/arcgis.html.md # ArcGIS ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `arcgis` | `social_core.backends.arcgis.ArcGISOAuth2` | ArcGIS uses OAuth2 for authentication. Accounts are associated by the provider’s stable user `id`. Associations created by older social-core releases used `username` and migrate on the next successful authentication. - Register a new application at [ArcGIS Developer Center](https://developers.arcgis.com/). ## OAuth2 1. Add the OAuth2 backend to your settings page: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.arcgis.ArcGISOAuth2', ... ) ``` 2. Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_ARCGIS_KEY = '' SOCIAL_AUTH_ARCGIS_SECRET = '' ``` # backends/auth0.html.md # Auth0 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `auth0` | `social_core.backends.auth0.Auth0OAuth2` | ## Auth0 OAuth2 Auth0 provides OAuth2 authentication. This is the original `Auth0OAuth2` backend. For a newer OpenID Connect implementation, see [Auth0 OpenID Connect](backends/auth0_openidconnect.html.md). ### Setup To enable Auth0 OAuth2 support: 1. Register your application at [Auth0 Dashboard](https://manage.auth0.com/) to get your Auth0 domain, Client ID, and Client Secret. 2. Fill in the settings with your Auth0 domain, Client ID, and Client Secret: ```default SOCIAL_AUTH_AUTH0_KEY = '' SOCIAL_AUTH_AUTH0_SECRET = '' SOCIAL_AUTH_AUTH0_DOMAIN = 'yourdomain.auth0.com' ``` Replace `yourdomain` with your Auth0 tenant domain. 3. Add the backend to your authentication backends: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.auth0.Auth0OAuth2', ... ) ``` ### Scopes You can define custom scopes using the `SOCIAL_AUTH_AUTH0_SCOPE` setting: ```default SOCIAL_AUTH_AUTH0_SCOPE = ['openid', 'profile', 'email'] ``` The backend will handle JWT token validation and extract user details including username, email, full name, and profile picture. # backends/auth0_openidconnect.html.md # Auth0 OpenID Connect ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-----------------------|-------------------------------------------------------------------| | `auth0_openidconnect` | `social_core.backends.auth0_openidconnect.Auth0OpenIdConnectAuth` | Auth0 OpenID Connect (OIDC) implementation. Separate from the previous `Auth0OAuth2` backend, as it builds on the base OIDC backend. ## IdP Setup To configure Auth0: 1. Log into your Auth0 Dashboard 2. Navigate to **Applications** > **Create Application** 3. Select **Regular Web Applications** 4. In the application settings, configure: * **Allowed Callback URLs**: `https://your-domain.com/complete/auth0-openidconnect/` * **Allowed Logout URLs**: `https://your-domain.com/logout/` (if using logout) * **Allowed Web Origins**: `https://your-domain.com` 5. Note the **Domain** (e.g., `mytenant.auth0.com`), **Client ID**, and **Client Secret** ## Application Configuration Use the values from your Auth0 application: ```default SOCIAL_AUTH_AUTH0_OPENIDCONNECT_DOMAIN = 'mytenant.auth0.com' SOCIAL_AUTH_AUTH0_OPENIDCONNECT_KEY = '' SOCIAL_AUTH_AUTH0_OPENIDCONNECT_SECRET = '' ``` ## Scopes The default scope is `["openid", "profile", "email"]`. In order to support refresh tokens/long-lived logins, you may want to add the `offline_access` scope: ```default SOCIAL_AUTH_AUTH0_OPENIDCONNECT_SCOPE = 'openid profile email offline_access' ``` # backends/azuread.html.md # Microsoft Entra ID and Azure AD B2C Microsoft Entra ID was formerly Azure Active Directory. Login buttons use the Microsoft title and logo following [Microsoft sign-in branding guidance](https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-branding-in-apps). Azure AD B2C retains its separate name. Backend identifiers and settings prefixes remain unchanged. ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------------------|-------------------------------------------------------------| | `azuread-oauth2` | `social_core.backends.azuread.AzureADOAuth2` | | `azuread-oauth2-v2` | `social_core.backends.azuread.AzureADOAuth2V2` | | `azuread-tenant-oauth2` | `social_core.backends.azuread_tenant.AzureADTenantOAuth2` | | `azuread-v2-tenant-oauth2` | `social_core.backends.azuread_tenant.AzureADV2TenantOAuth2` | | `azuread-b2c-oauth2` | `social_core.backends.azuread_b2c.AzureADB2COAuth2` | ## User identifiers The Azure backends use these claims as their default user identifiers: | Backend name | Default ID key | |----------------------------|------------------| | `azuread-oauth2` | `sub` | | `azuread-oauth2-v2` | `sub` | | `azuread-tenant-oauth2` | `sub` | | `azuread-v2-tenant-oauth2` | `sub` | | `azuread-b2c-oauth2` | `sub` | Microsoft documents `preferred_username` and `upn` as mutable human-readable identifiers that must not be used as authorization identities. The backends therefore use `sub`, which is immutable and pairwise unique to an application ID. The `oid` claim is immutable across applications within a tenant, but is only tenant-unique and must be combined with `tid` when used across tenants. For example, configure the v2 tenant backend to use `sub`: ```default SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_ID_KEY = 'sub' ``` Older associations using `upn` or `preferred_username` are migrated to `sub` during authentication. See [Configuration](configuration/settings.html.md) for the compatibility and strict migration policies. Because `sub` is pairwise, changing the Azure application/client ID can also require an identity migration. The `sub`, `oid`, and `tid` claims are retained in `extra_data` to make future verified migrations possible. See the [Microsoft ID token claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference). ## IdP Setup To configure Azure AD: 1. Log into the Azure Portal 2. Navigate to **Azure Active Directory** > **App registrations** > **New registration** 3. Configure: * **Name**: Your application name * **Redirect URI**: Select **Web** and enter `https://your-domain.com/complete/azuread-oauth2/` 4. After registration, note the **Application (client) ID** and **Directory (tenant) ID** 5. Create a client secret: * Go to **Certificates & secrets** > **New client secret** * Copy the secret value immediately (you won’t be able to see it again) 6. Configure API Permissions: * Go to **API permissions** > **Add a permission** > **Microsoft Graph** * Add delegated permissions: `User.Read`, `email`, `openid`, `profile` * Click **Grant admin consent** if required ## Scopes, tokens, and app roles An ID token identifies the signed-in user to your application. An access token authorizes calls to a particular API. Delegated API permissions are represented by the `scp` claim in the access token, not in the ID token. Requesting a scope such as `api:///user_impersonation` does not add `scp` to the ID token. See the [Microsoft access token claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/access-token-claims-reference). The `roles` claim can appear in an ID token when app roles are defined for the sign-in application and assigned to the user or group through **Enterprise applications**. When calling a separate API, define and assign roles for that API; those roles appear in its access token instead. Requesting API scopes does not assign app roles. See [Microsoft app role configuration](https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-app-roles-in-apps). Social-auth stores the original ID token in `UserSocialAuth.extra_data['id_token']` and makes its validated claims available in the authentication pipeline’s `response`. It does not add claims to the issued token. Decoded roles are not stored separately by default. To retain roles already present in the ID token, configure the selected backend’s `EXTRA_DATA` setting: ```default SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_EXTRA_DATA = [('roles', 'roles')] ``` This stores the claim as `UserSocialAuth.extra_data['roles']`; it does not assign Django groups or permissions. ### V2 tenant configuration Use `AzureADV2TenantOAuth2` for a tenant-specific integration using v2 scopes. For example, to request a delegated permission exposed by your API: ```default AUTHENTICATION_BACKENDS = ( 'social_core.backends.azuread_tenant.AzureADV2TenantOAuth2', 'django.contrib.auth.backends.ModelBackend', ) SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_KEY = '' SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_SECRET = '' SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_TENANT_ID = '' SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_SCOPE = [ 'api:///user_impersonation', ] ``` Replace the scope with the exact identifier exposed by your API, configure the client’s delegated API permission, and obtain consent as required. Register the matching **Web** redirect URI: ```default https://your-domain.com/complete/azuread-v2-tenant-oauth2/ ``` Configured scopes extend this backend’s defaults: `openid`, `profile`, and `offline_access`. To replace the defaults instead, set `SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_IGNORE_DEFAULT_SCOPE = True` and include the required OpenID Connect scopes in `SCOPE` yourself. See [Configuration](configuration/settings.html.md). The v1 backends `AzureADOAuth2` and `AzureADTenantOAuth2` use `RESOURCE` to select the target API. V2 backends use resource-qualified scopes instead. When switching to v2, change the backend class, settings prefix, and registered callback together. Switching versions does not make `scp` appear in an ID token or guarantee that app roles have been assigned. See [Microsoft scopes and permissions](https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc). ## Application Configuration Fill in `Client ID` and `Client Secret` settings with values from Azure AD: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_KEY = '' SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = '' ``` - For this v1 backend, select the target API with: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_RESOURCE = '' ``` This identifies the resource you would like to access after authentication succeeds; configure the permissions for that resource in the app registration. Some of the possible values are: `https://graph.windows.net` or `https://-my.sharepoint.com`. When using Microsoft Graph, the resource needed is: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_RESOURCE = 'https://graph.microsoft.com/' ``` - Add the backend to the authentication backends setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.azuread.AzureADOAuth2', ... ) ``` - If you are using an authority host other than the default `AZURE_PUBLIC_CLOUD` (`'login.microsoftonline.com'`) then you can override the default with the `AUTHORITY_HOST` setting. A list of Azure authority hosts can be found in the [Azure Authority Hosts](https://docs.microsoft.com/en-us/python/api/azure-identity/azure.identity.azureauthorityhosts?view=azure-python) doc: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_AUTHORITY_HOST = '' ``` - Federated identity credentials (client assertions) are supported when you do not want to use a client secret. After adding a federated credential to your Entra ID app, point the backend at the OIDC token that your workload issues (for example, Kubernetes service account tokens issued via Azure Workload Identity, or other OIDC tokens where you manage writing the token to a file). Precedence: if `SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET` is set, the backend uses the client secret and does not send a client assertion; otherwise it prefers an explicit `SOCIAL_AUTH_AZUREAD_OAUTH2_CLIENT_ASSERTION`; if no assertion is provided, it reads a token file from `AZURE_FEDERATED_TOKEN_FILE` (or `OAUTH2_FEDERATED_TOKEN_FILE`) or `SOCIAL_AUTH_AZUREAD_OAUTH2_FEDERATED_TOKEN_FILE`. The backend will automatically use a client assertion instead of `CLIENT_SECRET` when the secret is omitted. Default path used by Azure Workload Identity on Kubernetes: ```default AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/azure/tokens/azure-identity-token ``` Or configure explicitly via the backend setting: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_FEDERATED_TOKEN_FILE = '/path/to/oidc/token' ``` You can also provide a pre-built client assertion JWT (preferred when you already create the assertion yourself): ```default SOCIAL_AUTH_AZUREAD_OAUTH2_CLIENT_ASSERTION = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...' # Optional: defaults to the standard JWT bearer URN shown here SOCIAL_AUTH_AZUREAD_OAUTH2_CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' ``` Minimal configs by approach: - Token file (workload-issued OIDC token): leave `SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET` unset; set either `AZURE_FEDERATED_TOKEN_FILE` (or `OAUTH2_FEDERATED_TOKEN_FILE`) or `SOCIAL_AUTH_AZUREAD_OAUTH2_FEDERATED_TOKEN_FILE` to the token path. `CLIENT_ASSERTION_TYPE` is not needed for this mode. - Pre-built client assertion: leave `SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET` unset; set `SOCIAL_AUTH_AZUREAD_OAUTH2_CLIENT_ASSERTION` (and optionally `SOCIAL_AUTH_AZUREAD_OAUTH2_CLIENT_ASSERTION_TYPE` if you use a non-standard type). `FEDERATED_TOKEN_FILE` is not read in this mode because the explicit assertion wins. Kubernetes projected service account token volume example: ```default apiVersion: v1 kind: Pod metadata: name: mypod spec: serviceAccountName: myserviceaccount containers: - name: mycontainer image: myimage env: - name: AZURE_FEDERATED_TOKEN_FILE value: /var/run/secrets/azure/tokens/azure-identity-token volumeMounts: - name: azure-identity-token mountPath: /var/run/secrets/azure/tokens readOnly: true volumes: - name: azure-identity-token projected: sources: - serviceAccountToken: path: azure-identity-token audience: api://AzureADTokenExchange expirationSeconds: 3600 ``` These settings apply to Azure AD/Entra ID scenarios. For more information on workload identity, see [Workload Identity Federation](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation) and [Federated identity credentials (Workload Identity)](https://azure.github.io/azure-workload-identity/docs/topics/federated-identity-credential.html). ## Authority configuration Use `AUTHORITY_URL` to choose the host and sign-in audience together. For example, restrict sign-in to work and school accounts with: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_AUTHORITY_URL = 'https://login.microsoftonline.com/organizations' ``` The audience path is `common` for work, school, and personal Microsoft accounts, `organizations` for work and school accounts, or `consumers` for personal accounts. A tenant UUID or tenant domain selects a specific tenant. The app registration must also allow the chosen account types. See [Microsoft authorization code flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow). Specify an HTTPS base authority, including its audience or tenant path. Omit `/oauth2/authorize`, `/oauth2/token`, `/v2.0`, and discovery suffixes. The backend class selects v1 or v2 endpoints. Trailing slashes are normalized; credentials, query strings, and fragments are not accepted. Each backend has its own configuration prefix: | Backend | Authority setting | |----------------------------|------------------------------------------------------| | `azuread-oauth2` | `SOCIAL_AUTH_AZUREAD_OAUTH2_AUTHORITY_URL` | | `azuread-oauth2-v2` | `SOCIAL_AUTH_AZUREAD_OAUTH2_V2_AUTHORITY_URL` | | `azuread-tenant-oauth2` | `SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_AUTHORITY_URL` | | `azuread-v2-tenant-oauth2` | `SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_AUTHORITY_URL` | | `azuread-b2c-oauth2` | `SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_AUTHORITY_URL` | For example, use the v2 backend for organizational accounts: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_V2_AUTHORITY_URL = 'https://login.microsoftonline.com/organizations' ``` Or use a tenant backend with an explicit authority: ```default SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_AUTHORITY_URL = 'https://login.microsoftonline.com/your-tenant.onmicrosoft.com' SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_AUTHORITY_URL = 'https://login.microsoftonline.com/your-tenant.onmicrosoft.com' ``` An explicit authority supplies the base for authorization, token exchange, refresh, and discovery. Without it, existing `AUTHORITY_HOST`, `TENANT_ID`, and `TENANT_NAME` configuration continues to work. A UUID `TENANT_ID` in a tenant backend remains a token validation restriction even when the authority is overridden. Individual `AUTHORIZATION_URL`, `ACCESS_TOKEN_URL`, and `OPENID_CONFIGURATION_URL` overrides take precedence over the derived URLs. Token issuer, signing-key, tenant, and B2C policy validation remain enabled. For B2C custom domains, end the authority at the tenant domain and configure the policy separately: ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_TENANT_NAME = 'your-tenant' SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_AUTHORITY_URL = 'https://login.example.com/your-tenant.onmicrosoft.com' SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_POLICY = 'b2c_1_signin' ``` The backend retains its policy query parameters; do not append the policy to `AUTHORITY_URL`. ## Proof Key for Code Exchange (PKCE) All five Azure backends support PKCE. It is disabled by default to preserve existing integrations. Enable it with the selected backend’s setting: ```default SOCIAL_AUTH_AZUREAD_OAUTH2_USE_PKCE = True # For the other backends, use the corresponding setting instead: SOCIAL_AUTH_AZUREAD_OAUTH2_V2_USE_PKCE = True SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_USE_PKCE = True SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_USE_PKCE = True SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_USE_PKCE = True ``` The default challenge method is `S256`. The backend saves a random verifier in the session, sends its SHA-256 challenge at authorization, and sends the verifier when redeeming the code. PKCE complements client authentication; continue to configure a client secret or federated assertion for confidential clients. V2 backends are recommended for new integrations. Register server-side callbacks as **Web** redirect URIs, including applications with a separate frontend. Enabling PKCE alone does not make a server-side flow compatible with an Azure **SPA** registration: Microsoft also requires an `Origin` header for SPA token redemption and restricts client credentials when that header is present. See [Microsoft authorization code flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow). ## Token renewal `backend.get_auth_token(user_id)` returns the stored access token and renews it when its stored expiry indicates it has expired. Renewal requires a stored refresh token. If the token is expired and no refresh token is available, it raises `AuthCredentialError` with `code='reauthentication_required'` and `stage='refresh'` instead of returning the expired token. Arrange another provider login to obtain new credentials. See [Token renewal](backends/oauth.html.md#oauth-token-renewal) for the shared renewal behavior. ## Tenant Support If the app is linked to a specific tenant (vs the common tenant) it’s possible to use a version of the backend with tenant support. ### IdP Setup for Tenant Follow the same IdP setup steps from the ‘IdP Setup’ section above, but use redirect URI: ```default https://your-domain.com/complete/azuread-tenant-oauth2/ ``` ### Application Configuration for Tenant Fill in `Client ID`, `Client Secret`, and `Tenant ID` settings: ```default SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = '' SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = '' SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = '' ``` - For this v1 backend, select the target API with: ```default SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_RESOURCE = '' ``` This identifies the resource you would like to access after authentication succeeds; configure the permissions for that resource in the app registration. Some of the possible values are: `https://graph.windows.net` or `https://-my.sharepoint.com`. When using Microsoft Graph, the resource needed is: ```default SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_RESOURCE = 'https://graph.microsoft.com/' ``` - Add the backend to the authentication backends setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.azuread_tenant.AzureADTenantOAuth2', ... ) ``` - If you are using an authority host other than the default `AZURE_PUBLIC_CLOUD` (‘login.microsoftonline.com’) then you can override the default with the `AUTHORITY_HOST` setting. The Azure authority hosts are listed in the [Azure Authority Hosts](https://docs.microsoft.com/en-us/python/api/azure-identity/azure.identity.azureauthorityhosts?view=azure-python) doc: ```default SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_AUTHORITY_HOST = '' ``` ## B2C Tenant If the app needs custom business logic for authentication then use the Azure AD B2C tenant. To enable OAuth2 B2C Tenant support: - Fill in `Client ID` and `Client Secret` settings. These values can be obtained easily as described in [Azure AD Application Registration](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) doc: ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_KEY = '' SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_SECRET = '' ``` - Fill in the tenant name (without `.onmicrosoft.com`): ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_TENANT_NAME = '' ``` - Fill in the B2C policy: ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_POLICY = '' ``` The policy should start with b2c_. For more information see [Azure AD B2C User flows and custom policies overview](https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview) doc. - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_RESOURCE = '' ``` This is the resource you would like to access after authentication succeeds. Some of the possible values are: `https://graph.windows.net` or `https://-my.sharepoint.com`. When using Microsoft Graph, the resource needed is: ```default SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_RESOURCE = 'https://graph.microsoft.com/' ``` - Add the backend to the authentication backends setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.azuread_b2c.AzureADB2COAuth2', ... ) ``` - If you are using an authority host other than the default `AZURE_PUBLIC_CLOUD` (‘b2clogin.com’) then you can override the default with the `AUTHORITY_HOST` setting. > SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_AUTHORITY_HOST = ‘’ ## B2C provider logout `AzureADB2COAuth2.logout_url()` returns the provider logout URL from the configured policy’s OpenID Connect `end_session_endpoint`. It preserves endpoint query parameters and includes the configured client ID. It does not send a request or clear the application’s session. The optional keyword arguments are `post_logout_redirect_uri`, `id_token_hint`, and `state`. Pass the previously issued ID token from `extra_data` as the hint. Configure a trusted return URL and register it with your B2C application. When B2C requires an ID token for logout, it checks the return URL against registered redirect URIs. If using `state`, save it and verify it on the return callback. See [Microsoft B2C sign-out](https://learn.microsoft.com/en-us/azure/active-directory-b2c/openid-connect#send-a-sign-out-request). Build the URL using the same policy that authenticated the user. For example, a Django view can retrieve the token before clearing the local session: ```python from django.contrib.auth import logout from django.contrib.auth.decorators import login_required from django.shortcuts import redirect from django.views.decorators.http import require_POST from social_django.utils import load_backend, load_strategy @login_required @require_POST def b2c_logout(request): social = request.user.social_auth.get(provider='azuread-b2c-oauth2') strategy = load_strategy(request) backend = load_backend( strategy, 'azuread-b2c-oauth2', redirect_uri=None ) provider_url = backend.logout_url( post_logout_redirect_uri=request.build_absolute_uri('/signed-out/'), id_token_hint=social.extra_data.get('id_token'), ) logout(request) return redirect(provider_url) ``` Use a CSRF-protected POST form to invoke this view. This example assumes an authenticated B2C user and a single configured sign-in policy. Applications with multiple policies must select the backend for the stored sign-in policy. A missing or invalid `end_session_endpoint` raises `AuthResponseError` with `code="missing_claim"` or `code="invalid_claim"`, respectively; discovery request failures propagate through the usual backend error handling. Provider logout complements local logout. Disconnecting an account removes its association instead; see [Disconnect and Logging Out](logging_out.html.md). ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/battlenet.html.md # Battle.net ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |--------------------|--------------------------------------------------| | `battlenet-oauth2` | `social_core.backends.battlenet.BattleNetOAuth2` | Blizzard implemented OAuth2 protocol for their authentication mechanism. To enable `python-social-auth` support follow this steps: 1. Go to [Battlenet Developer Portal](https://dev.battle.net/) and create an application. 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_BATTLENET_OAUTH2_KEY = '...' SOCIAL_AUTH_BATTLENET_OAUTH2_SECRET = '...' ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.battlenet.BattleNetOAuth2', ... ) ``` Note: If you want to allow the user to choose a username from their own characters, some further steps are required, see the use cases part of the documentation. To get the account id and battletag use the user_data function, as [account id is no longer passed inherently](http://us.battle.net/en/forum/topic/18300183303). Another note: If you get a 500 response “Internal Server Error” the API now requires [https on callback endpoints](http://us.battle.net/en/forum/topic/17085510584). Further documentation at [Developer Guide](https://dev.battle.net/docs/read/oauth). # backends/behance.html.md # Behance ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `behance` | `social_core.backends.behance.BehanceOAuth2` | ## DEPRECATED NOTICE **NOTE:** IT SEEMS THAT BEHANCE HAS DROPPED THEIR OAUTH2 SUPPORT WITHOUT MUCH NOTICE BESIDE A [BLOG POST](http://blog.behance.net/dev/introducing-the-behance-api) ON SEPTEMBER 2014 MENTIONING THAT IT WILL BE INTRODUCED “SOON”. THIS BACKEND IS IN DEPRECATED STATE FOR NOW. Behance uses OAuth2 for its auth mechanism. - Register a new application at [Behance App Registration](http://www.behance.net/dev/register), set your application name, website and redirect URI. - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_BEHANCE_KEY = '' SOCIAL_AUTH_BEHANCE_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_BEHANCE_SCOPE = [...] ``` Check available permissions at [Possible Scopes](http://www.behance.net/dev/authentication#scopes). Also check the rest of their doc at [Behance Developer Documentation](http://www.behance.net/dev). # backends/belgium_eid.html.md # Belgium EID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `belgiumeid` | `social_core.backends.belgiumeid.BelgiumEIDOpenId` | Belgium EID OpenID doesn’t require major settings beside being defined on `AUTHENTICATION_BACKENDS``: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.belgiumeid.BelgiumEIDOpenId', ... ) ``` # backends/bitbucket.html.md # Bitbucket ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |--------------------|--------------------------------------------------| | `bitbucket-oauth2` | `social_core.backends.bitbucket.BitbucketOAuth2` | Bitbucket supports both OAuth2 and OAuth1 logins. 1. Register a new OAuth Consumer by following the instructions in the Bitbucket documentation: [OAuth on Bitbucket](https://confluence.atlassian.com/display/BITBUCKET/OAuth+on+Bitbucket) Note: For OAuth2, your consumer MUST have the “account” scope otherwise the user profile information (username, name, etc.) won’t be accessible. 2. Configure the appropriate settings for OAuth2 or OAuth1 (see below). ## OAuth2 - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_BITBUCKET_OAUTH2_KEY = '' SOCIAL_AUTH_BITBUCKET_OAUTH2_SECRET = '' ``` - If you would like to restrict access to only users with verified e-mail addresses, set `SOCIAL_AUTH_BITBUCKET_OAUTH2_VERIFIED_EMAILS_ONLY = True` By default the setting is set to `False` since it’s possible for a project to gather this information by other methods. ## OAuth1 - OAuth1 works similarly to OAuth2, but you must fill in the following settings instead: ```default SOCIAL_AUTH_BITBUCKET_KEY = '' SOCIAL_AUTH_BITBUCKET_SECRET = '' ``` - If you would like to restrict access to only users with verified e-mail addresses, set `SOCIAL_AUTH_BITBUCKET_VERIFIED_EMAILS_ONLY = True`. By default the setting is set to `False` since it’s possible for a project to gather this information by other methods. ## User ID Bitbucket recommends the use of [UUID](https://confluence.atlassian.com/display/BITBUCKET/Use+the+Bitbucket+REST+APIs) as the user identifier instead of `username` since they can change and impose a security risk. For that reason `UUID` is used by default, but for backward compatibility reasons, it’s possible to get the old behavior again by defining this setting: ```default SOCIAL_AUTH_BITBUCKET_USERNAME_AS_ID = True ``` # backends/bitbucket_datacenter_oauth2.html.md # Bitbucket Data Center OAuth2 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-------------------------------|-----------------------------------------------------------------------| | `bitbucket-datacenter-oauth2` | `social_core.backends.bitbucket_datacenter.BitbucketDataCenterOAuth2` | Bitbucket Data Center (previously Bitbucket Server) supports the [OAuth 2.0](https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html) protocol. It supports two types of OAuth 2.0 flows: 1. Authorization code with [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) 2. Authorization code ## Configuration 1. Register a new [Application Link](https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html) in your Bitbucket Data Center instance. 2. Provide the host URL of your Bitbucket Data Center instance: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_URL = "https://my-bitbucket-server.acme.com" ``` 3. Fill *Client ID* in `SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_KEY` and *Client Secret* in `SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_SECRET` in your project settings: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_KEY = "..." SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_SECRET = "..." ``` 4. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... "social_core.backends.bitbucket_datacenter.BitbucketDataCenterOAuth2", ... ) ``` ## Extra Configuration - You can specify the scope that your application requires: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_SCOPE = ["PUBLIC_REPOS"] ``` You can see all possible values at [Bitbucket Data Center OAuth 2.0 provider API](https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes). By default, `PUBLIC_REPOS` is set. - You can choose to disable PKCE: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_USE_PKCE = False ``` By default, True is set. - You can specify PKCE challenge method: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_PKCE_CODE_CHALLENGE_METHOD = '...' ``` The possible values for this are `s256` and `plain`. By default, `s256` is set. You can see more information about PKCE at [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). - You can specify the user’s avatar size: ```default SOCIAL_AUTH_BITBUCKET_DATACENTER_OAUTH2_USER_AVATAR_SIZE = 48 ``` This is the size of the user’s avatar requested from the API which is stored in `EXTRA_DATA["avatar_url"]`. By default, `48` is set. # backends/box.html.md # Box.net ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------| | `box` | `social_core.backends.box.BoxOAuth2` | Box works similar to Facebook (OAuth2). - Register an application at [Manage Box Applications](https://app.box.com/developers/services) - Fill the **Consumer Key** and **Consumer Secret** values in your settings: ```default SOCIAL_AUTH_BOX_KEY = '' SOCIAL_AUTH_BOX_SECRET = '' ``` - By default the token is not permanent, it will last an hour. To refresh the access token just do: ```default from social_django.utils import load_strategy strategy = load_strategy(backend='box') user = User.objects.get(pk=foo) social = user.social_auth.filter(provider='box')[0] social.refresh_token(strategy=strategy) ``` # backends/bungie.html.md # Bungie ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `bungie` | `social_core.backends.bungie.BungieOAuth2` | Bungie uses OAuth 2.0 for authentication. - Bungie does not return username, email or name information. They return a short form membership id (bungie site account) that is then stored as the uid for social auth. To get the username, \_GetBungieNetUser_ is called which returns the bungie.net profile, including user name as the \_displayName_ field. You may super the `get_user_details` function to change behavior or redirect your users to a partial pipeline flow that gathers missing user data such as email, password (local to your site), first name, last name etc. Interrupt the pipeline immediately after `get_username`, as shown in the sample pipeline below: ```default SOCIAL_AUTH_PIPELINE = ( # Get the information we can about the user and return it in a simple # format to create the user instance later. On some cases the details are # already part of the auth response from the provider, but sometimes this # could hit a provider API. 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', # Get the social uid from whichever service we're authing thru. The uid is # the unique identifier of the given user in the provider. 'social_core.pipeline.social_auth.social_uid', # Verifies that the current auth process is valid within the current # project, this is where emails and domains whitelists are applied (if # defined). # Super'ed in bungie.py 'social_core.pipeline.social_auth.auth_allowed', # Checks if the current social-account is already associated in the site. 'social_core.pipeline.social_auth.social_user', # Make up a username for this person, appends a random string at the end if # there's any collision. 'social_core.pipeline.user.get_username', # Redirect to an @partial view to get missing user information here. # If you wish to validate or associate by email, this is required. # '.pipeline.required_user_information', # Send a validation email to the user to verify its email address. # Disabled by default. # 'social_core.pipeline.mail.mail_validation', # Associates the current social details with another user account with # a similar email address. Disabled by default. # 'social_core.pipeline.social_auth.associate_by_email', # Create a user account if we haven't found one yet. 'social_core.pipeline.user.create_user', # Create the record that associates the social account with the user. 'social_core.pipeline.social_auth.associate_user', # Populate the extra_data field in the social record with the values # specified by settings (and the default ones like access_token, etc). 'social_core.pipeline.social_auth.load_extra_data', # Update the user record with any changed info from the auth service. 'social_core.pipeline.user.user_details', ) ``` - Register a new application at [https://www.bungie.net/en/Application/](https://www.bungie.net/en/Application/) - Set the `Callback URL` in the Bungie.net Application Registration page to `https:///complete/bungie` This **must** be `https`. During development you can use stunnel to proxy the request or you can install sslserver from pip. - Set the `Authentication Backend`, `Client ID (aka OAuth Key)`, `OAuth Secret`, and `X-API-KEY` values in your Django settings: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.bungie.BungieOAuth2', ... ) SOCIAL_AUTH_BUNGIE_API_KEY = '...' SOCIAL_AUTH_BUNGIE_KEY = '' SOCIAL_AUTH_BUNGIE_SECRET = '...' SOCIAL_AUTH_BUNGIE_ORIGIN = '...' ``` - Bungie allows whitespace in usernames, modify these if needed: ```default SOCIAL_AUTH_SLUGIFY_USERNAMES = False SOCIAL_AUTH_CLEAN_USERNAMES = False SOCIAL_AUTH_USER_MODEL = 'auth.User' ``` # backends/cas.html.md # CAS (OpenID Connect via Apereo CAS) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------------| | `cas` | `social_core.backends.cas.CASOpenIdConnectAuth` | The [CAS](https://apereo.github.io/cas/6.6.x/authentication/OIDC-Authentication.html) backend allows authentication against an Apereo CAS OIDC provider. The backend class is CASOpenIdConnectAuth with name cas. A minimum configuration is: ```default SOCIAL_AUTH_CAS_OIDC_ENDPOINT = 'https://.....' SOCIAL_AUTH_CAS_KEY = '' SOCIAL_AUTH_CAS_SECRET = '' ``` The remaining configuration will be auto-detected, by fetching: ```default /.well-known/openid-configuration ``` This class functions identically to the generic OIDC backend, but hides the differences in implementation details of the OIDC implementation in Apereo CAS. ## User identification Accounts are associated by the OpenID Connect `sub` claim. Associations created by older social-core releases used the normalized username and migrate on the next successful authentication. Note that despite the naming of the backend, this is NOT an implementation of the CAS protocol, also supported by Apereo CAS. The CAS backend is only intended as a way to use the Apereo CAS identity provider as an authentication service, but via OIDC. ## Username The [CAS](https://apereo.github.io/cas/6.6.x/authentication/OIDC-Authentication.html) backend will check for a `preferred_username` key in the values returned by the server. If the username is under a different key, this can be overridden: ```default SOCIAL_AUTH_CAS_USERNAME_KEY = 'nickname' ``` This setting indicates that the username should be populated by the `nickname` claim instead. ## Scopes The default set of scopes requested are “openid”, “profile” and “email”. You can request additional claims, for example: ```default SOCIAL_AUTH_CAS_SCOPE = ['groups'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_CAS_IGNORE_DEFAULT_SCOPE = True ``` ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/cesid.html.md # CESiD AAI - Czech Educational and Scientific Identification AAI ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------------| | `cesid` | `social_core.backends.cesid.CesidOpenIdConnect` | CESiD’s OpenID Connect (OIDC) backend requires the following minimum configuration: ```default SOCIAL_AUTH_CESID_OIDC_KEY = '' SOCIAL_AUTH_CESID_OIDC_SECRET = '' ``` ## Scopes The default scopes will include the user’s email. You can request additional claims, for example: ```default SOCIAL_AUTH_CESID_OIDC_SCOPE = ['eduperson_entitlement'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_CESID_OIDC_IGNORE_DEFAULT_SCOPE = True ``` # backends/cognito.html.md # Cognito ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `cognito` | `social_core.backends.cognito.CognitoOAuth2` | Cognito implemented OAuth2 protocol for their authentication mechanism. To enable `python-social-auth` support follow this steps: Accounts are associated by the immutable `sub` claim. Associations created by older social-core releases used `username` and migrate on the next successful authentication. 1. Go to [AWS Cognito Console](https://console.aws.amazon.com/cognito/home) and select `Manage User Pools`. 2. Choose an existing pool or create a new one following the [Cognito Pool Tutorial](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html). 3. Create an app (make sure to generate a client secret) and configure a pool domain ([Cognito App Configuration](GettingStartedforWeb:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html)): ```default SOCIAL_AUTH_COGNITO_KEY = '...' SOCIAL_AUTH_COGNITO_SECRET = '...' SOCIAL_AUTH_COGNITO_POOL_DOMAIN = '...' ``` 4. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.cognito.CognitoOAuth2', ... ) ``` # backends/coinbase.html.md # Coinbase ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `coinbase` | `social_core.backends.coinbase.CoinbaseOAuth2` | Coinbase uses OAuth2. - Register an application at [Coinbase](https://coinbase.com/oauth/applications/new) - Fill in the **Client Id** and **Client Secret** values in your settings: ```default SOCIAL_AUTH_COINBASE_KEY = '' SOCIAL_AUTH_COINBASE_SECRET = '' ``` - Set the `redirect_url` on coinbase. Make sure to include the trailing slash, eg. `http://hostname/complete/coinbase/` - Specify scopes with: ```default SOCIAL_AUTH_COINBASE_SCOPE = [...] ``` By default the scope is set to `balance`. - extra scopes can be defined by using: ```default SOCIAL_AUTH_COINBASE_AUTH_EXTRA_ARGUMENTS = {'account': 'all'} ``` # backends/coursera.html.md # Coursera ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `coursera` | `social_core.backends.coursera.CourseraOAuth2` | Coursera uses a variant of OAuth2 authentication. The details of the API can be found at [OAuth2-based APIs - Coursera Technology](https://tech.coursera.org/app-platform/oauth2/). Take the following steps in order to use the backend: 1. Create an account at [Coursera](https://accounts.coursera.org/console). 2. Open [Developer Console](https://accounts.coursera.org/console), create an organisation and application. 3. Set **Client ID** as a `SOCIAL_AUTH_COURSERA_KEY` and **Secret Key** as a `SOCIAL_AUTH_COURSERA_SECRET` in your local settings. 1. Add the backend to `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.coursera.CourseraOAuth2', ... ) ``` # backends/dailymotion.html.md # DailyMotion ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------------| | `dailymotion` | `social_core.backends.dailymotion.DailymotionOAuth2` | DailyMotion uses OAuth2. In order to enable the backend follow: Accounts are associated by the stable provider `id`. Associations created by older social-core releases used the renameable screen name and migrate on the next successful authentication. - Register an application at [DailyMotion Developer Portal](http://www.dailymotion.com/profile/developer/new) - Fill in the **Client Id** and **Client Secret** values in your settings: ```default SOCIAL_AUTH_DAILYMOTION_KEY = '' SOCIAL_AUTH_DAILYMOTION_SECRET = '' ``` - Set the `Callback URL` to `http:///complete/dailymotion/` - Specify scopes with: ```default SOCIAL_AUTH_DAILYMOTION_SCOPE = [...] ``` Available scopes are listed in the [Requesting Extended Permissions](http://www.dailymotion.com/doc/api/authentication.html#requesting-extended-permissions) section. # backends/digitalocean.html.md # DigitalOcean ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------------------| | `digitalocean` | `social_core.backends.digitalocean.DigitalOceanOAuth` | DigitalOcean uses OAuth2 for its auth process. See the full [DigitalOcean developer’s documentation](https://developers.digitalocean.com/documentation/) for more information. - Register a new application in the [Apps & API page](https://cloud.digitalocean.com/settings/applications) in the DigitalOcean control panel, setting the callback URL to `http://example.com/complete/digitalocean/` replacing `example.com` with your domain. - Fill the `Client ID` and `Client Secret` values from GitHub in the settings: ```default SOCIAL_AUTH_DIGITALOCEAN_KEY = '' SOCIAL_AUTH_DIGITALOCEAN_SECRET = '' ``` - By default, only `read` permissions are granted. In order to create, destroy, and take other actions on the user’s resources, you must request `read write` permissions like so: ```default SOCIAL_AUTH_DIGITALOCEAN_AUTH_EXTRA_ARGUMENTS = {'scope': 'read write'} ``` # backends/discogs.html.md # Discogs ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `discogs` | `social_core.backends.discogs.DiscogsOAuth1` | Discogs uses OAuth v1 for Authentication. - Register a new application int the [Discogs API settings](_discogs_settings), and - Add the Discogs backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... "social_core.backends.discogs.DiscogsOAuth1", ... ) ``` - Add the `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_DISCOGS_KEY = '' SOCIAL_AUTH_DISCOGS_SECRET = '' ``` Check [Discogs API documentation](_discogs_docs) for details. # backends/discord.html.md # Discord ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `discord` | `social_core.backends.discord.DiscordOAuth2` | Discord uses OAuth2 for authentication. - Register a new application at the [Discord Developer Portal](https://discord.com/developers/applications), set the callback URL to `http://example.com/complete/discord/` replacing `example.com` with your domain. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_DISCORD_KEY = '' SOCIAL_AUTH_DISCORD_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_DISCORD_SCOPE = [...] ``` See available scopes at [Discord OAuth2 Scopes](https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes). # backends/discourse.html.md # Discourse ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `discourse` | `social_core.backends.discourse.DiscourseAuth` | Discourse can serve as a Single Sign On provider for Authentication. The backend binds the local association to Discourse’s `external_id`. Email addresses remain profile data and are not account identifiers because they can change or later belong to another user. - Deploy a Discourse application and configure the application to enable Discourse as an SSO provider. - Fill in the shared secret and url of the Discourse server in the settings: ```default SOCIAL_AUTH_DISCOURSE_SECRET = "myDiscourseSecret" SOCIAL_AUTH_DISCOURSE_SERVER_URL = "https://my-discourse-site.com" ``` ## Using multiple Discourse instances Since Discourse is a distributed application, multiple Discourse instances can be used as SSO providers. If this is the case, the DiscourseAuth class can be extended and configured as follows: ```default from social_core.backends.discourse import DiscourseAuth class DiscourseAuthFoo(DiscourseAuth): name = 'discourse-foo' class DiscourseAuthBar(DiscourseAuth): name = 'discourse-bar' ``` Fill in the settings like so: ```default SOCIAL_AUTH_DISCOURSE_FOO_SECRET = "myDiscourseFooSecret" SOCIAL_AUTH_DISCOURSE_FOO_SERVER_URL = "https://my-discourse-foo-site.com" SOCIAL_AUTH_DISCOURSE_BAR_SECRET = "myDiscourseBarSecret" SOCIAL_AUTH_DISCOURSE_BAR_SERVER_URL = "https://my-discourse-bar-site.com" ``` ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/disqus.html.md # Disqus ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `disqus` | `social_core.backends.disqus.DisqusOAuth2` | Disqus uses OAuth v2 for Authentication. - Register a new application at the [Disqus API](http://disqus.com/api/applications/), and - fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_DISQUS_KEY = '' SOCIAL_AUTH_DISQUS_SECRET = '' ``` - extra scopes can be defined by using: ```default SOCIAL_AUTH_DISQUS_AUTH_EXTRA_ARGUMENTS = {'scope': 'likes comments relationships'} ``` Check [Disqus Auth API](http://disqus.com/api/docs/auth/) for details. # backends/docker.html.md # Docker ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `docker` | `social_core.backends.docker.DockerOAuth2` | ## Docker.io OAuth2 Docker.io now supports OAuth2 for their API. In order to set it up: - Register a new application by following the instructions in their website: [Register Your Application](http://docs.docker.io/en/latest/reference/api/docker_io_oauth_api/#register-your-application) - Fill **Consumer Key** and **Consumer Secret** values in settings: ```default SOCIAL_AUTH_DOCKER_KEY = '' SOCIAL_AUTH_DOCKER_SECRET = '' ``` - Add `'social_core.backends.docker.DockerOAuth2'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. # backends/douban.html.md # Douban ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-----------------|--------------------------------------------| | `douban-oauth2` | `social_core.backends.douban.DoubanOAuth2` | Douban supports OAuth2. Recently Douban launched their OAuth2 support and the new developer site, you can find documentation at [Douban Developers](http://developers.douban.com/). To setup OAuth2 follow: - Register a new application at [Create A Douban App](http://developers.douban.com/apikey/apply), make sure to mark the **web application** checkbox. - Fill **Consumer Key** and **Consumer Secret** values in settings: ```default SOCIAL_AUTH_DOUBAN_OAUTH2_KEY = '' SOCIAL_AUTH_DOUBAN_OAUTH2_SECRET = '' ``` - Add `'social_core.backends.douban.DoubanOAuth2'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. # backends/dribbble.html.md # Dribbble ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `dribbble` | `social_core.backends.dribbble.DribbbleOAuth2` | Dribbble - Register a new application at [Dribbble](https://dribbble.com/account/applications/new), set the callback URL to `http://example.com/complete/dribbble/` replacing `example.com` with your domain. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_DRIBBBLE_KEY = '' SOCIAL_AUTH_DRIBBBLE_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_DRIBBBLE_SCOPE = [...] ``` See auth scopes at [Dribbble Developer docs](http://developer.dribbble.com/v1/oauth/). # backends/drip.html.md # Drip ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------| | `drip` | `social_core.backends.drip.DripOAuth` | Drip uses OAuth v2 for Authentication. - Register a new application with [Drip](https://www.getdrip.com/user/applications), and - fill `Client ID` and `Client Secret` from getdrip.com values in the settings: ```default SOCIAL_AUTH_DRIP_KEY = '' SOCIAL_AUTH_DRIP_SECRET = '' ``` # backends/dropbox.html.md # Dropbox ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |------------------|------------------------------------------------| | `dropbox-oauth2` | `social_core.backends.dropbox.DropboxOAuth2V2` | Dropbox supports OAuth2. - Register a new application at [Dropbox Developers](https://www.dropbox.com/developers/apps). ## OAuth2 Api V2 Add the Dropbox OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.dropbox.DropboxOAuth2V2', ... ) ``` - Fill `App Key` and `App Secret` values in the settings: ```default SOCIAL_AUTH_DROPBOX_OAUTH2_KEY = '' SOCIAL_AUTH_DROPBOX_OAUTH2_SECRET = '' ``` # backends/email.html.md # Email Auth ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `email` | `social_core.backends.email.EmailAuth` | [python-social-auth](https://github.com/python-social-auth) comes with an [EmailAuth](https://github.com/python-social-auth/social-core/blob/master/social_core/backends/email.py) backend which comes handy when your site uses requires the plain old email and password authentication mechanism. Actually that’s a lie since the backend doesn’t handle password at all, that’s up to the developer to validate the password in and the proper place to do it is the pipeline, right after the user instance was retrieved or created. The reason to leave password handling to the developer is because too many things are really tied to the project, like the field where the password is stored, salt handling, password hashing algorithm and validation. So just add the pipeline functions that will do that following the needs of your project. ## Backend settings `SOCIAL_AUTH_EMAIL_FORM_URL = '/login-form/'` : Used to redirect the user to the login/signup form, it must have at least one field named `email`. Form submit should go to `/complete/email`, or if it goes to your view, then your view should complete the process calling `social_core.actions.do_complete`. `SOCIAL_AUTH_EMAIL_FORM_HTML = 'login_form.html'` : The template will be used to render the login/signup form to the user, it must have at least one field named `email`. Form submit should go to `/complete/email`, or if it goes to your view, then your view should complete the process calling `social_core.actions.do_complete`. ## Email validation Check *Email validation* pipeline in the [pipeline docs](../pipeline.html#email-validation). ## Password handling Here’s an example of password handling to add to the pipeline: ```default from social_core.exceptions import AuthCredentialError def user_password(strategy, backend, user, is_new=False, *args, **kwargs): if backend.name != 'email': return password = strategy.request_data()['password'] if is_new: user.set_password(password) user.save() elif not user.validate_password(password): # return {'user': None, 'social': None} raise AuthCredentialError( backend, code="credential_rejected", source="request", stage="pipeline", parameter="password", recovery="correct_input", ) ``` # backends/etsy.html.md # Etsy OAuth2 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `etsy` | `social_core.backends.etsy.EtsyOAuth2` | Etsy supports the [OAuth 2.0](https://developer.etsy.com/documentation/essentials/authentication) protocol using Authorization code with [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) flow. ## Configuration 1. Register a new [Application Link](https://developer.etsy.com/documentation/#developing-a-new-open-api-app) in your Etsy Account. 2. Fill *Client ID* in `SOCIAL_AUTH_ETSY_OAUTH2_KEY` in your project settings: ```default SOCIAL_AUTH_ETSY_OAUTH2_KEY = "..." ``` Note: *Client Secret* isn’t required via this flow. 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... "social_core.backends.etsy.EtsyOAuth2", ... ) ``` ## Extra Configuration - You can specify the scope that your application requires: ```default SOCIAL_AUTH_ETSY_OAUTH2_SCOPE = ["shops_r", "shops_w", ...] ``` You can see all possible values at [Etsy OAuth 2.0 provider API Scopes](https://developer.etsy.com/documentation/essentials/authentication/#scopes). - You can specify PKCE challenge method: ```default SOCIAL_AUTH_ETSY_OAUTH2_PKCE_CODE_CHALLENGE_METHOD = '...' ``` The possible value for this is only `S256` which is set by default. You can see more information about PKCE at [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). # backends/eventbrite.html.md # Eventbrite OAuth ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `eventbrite` | `social_core.backends.eventbrite.EventbriteOAuth2` | Eventbrite OAuth 2.0 for its authentication workflow. - Register a new application at Account Settings in [App Management](https://www.eventbrite.com/myaccount/apps/). - Fill `Consumer Key` and `Consumer Secret` values in the settings using `Application Key` and `OAuth Client Secret` provided by Eventbrite’s created app: ```default SOCIAL_AUTH_EVENTBRITE_KEY = '' SOCIAL_AUTH_EVENTBRITE_SECRET = '' ``` # backends/eveonline.html.md # EVE Online Single Sign-On (SSO) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `eveonline` | `social_core.backends.eveonline.EVEOnlineOAuth2` | The EVE Single Sign-On (SSO) works similar to GitHub (OAuth2). - Register a new application at [EVE Developers](https://developers.eveonline.com/), set the callback URL to `http://example.com/complete/eveonline/` replacing `example.com` with your domain. - Fill the `Client ID` and `Secret Key` values from EVE Developers in the settings: ```default SOCIAL_AUTH_EVEONLINE_KEY = '' SOCIAL_AUTH_EVEONLINE_SECRET = '' ``` - If you want to use EVE Character names as user names, use this setting: ```default SOCIAL_AUTH_CLEAN_USERNAMES = False ``` - If you want to access EVE Online’s CREST API, use: ```default SOCIAL_AUTH_EVEONLINE_SCOPE = ['publicData'] ``` # backends/evernote.html.md # Evernote OAuth ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |--------------------|------------------------------------------------------| | `evernote` | `social_core.backends.evernote.EvernoteOAuth` | | `evernote-sandbox` | `social_core.backends.evernote.EvernoteSandboxOAuth` | Evernote OAuth 1.0 for its authentication workflow. - Register a new application at [Evernote API Key form](http://dev.evernote.com/support/api_key.php). - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_EVERNOTE_KEY = '' SOCIAL_AUTH_EVERNOTE_SECRET = '' ``` ## Sandbox Evernote supports a sandbox mode for testing, there’s a custom backend for it which name is `evernote-sandbox` instead of `evernote`. Same settings apply but use these instead: ```default SOCIAL_AUTH_EVERNOTE_SANDBOX_KEY = '' SOCIAL_AUTH_EVERNOTE_SANDBOX_SECRET = '' ``` # backends/facebook.html.md # Facebook ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------------------| | `facebook` | `social_core.backends.facebook.FacebookOAuth2` | | `facebook-app` | `social_core.backends.facebook.FacebookAppOAuth2` | Python Social Auth provides multiple backends for Facebook authentication: - **FacebookOAuth2** (`social_core.backends.facebook.FacebookOAuth2`) - Standard Facebook OAuth2 authentication - **FacebookAppOAuth2** (`social_core.backends.facebook.FacebookAppOAuth2`) - For Facebook Canvas Applications - **FacebookLimitedLogin** (`social_core.backends.facebook_limited.FacebookLimitedLogin`) - For Facebook Limited Login (iOS SDK) ## Token renewal Facebook OAuth2 and Facebook App renew credentials by exchanging the stored access token with `grant_type=fb_exchange_token`. A stored `refresh_token` is not required for these backends. Use `social.refresh_token(strategy)` for an explicit exchange or `social.get_access_token(strategy)` to exchange when the stored access token has expired. See [Token renewal](backends/oauth.html.md#oauth-token-renewal) for expiry handling and renewal failures. ## OAuth2 Facebook uses OAuth2 for its auth process. Further documentation at [Facebook development resources](http://developers.facebook.com/docs/authentication/): - Register a new application at [Facebook App Creation](https://developers.facebook.com/apps/), don’t use `localhost` as `App Domains` and `Site URL` since Facebook won’t allow them. Use a placeholder like `myapp.com` and define that domain in your `/etc/hosts` or similar file. - Add the Facebook OAuth2 backend to your `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.facebook.FacebookOAuth2', ... ) ``` - fill `App Id` and `App Secret` values in values: ```default SOCIAL_AUTH_FACEBOOK_KEY = '' SOCIAL_AUTH_FACEBOOK_SECRET = '' ``` - Define `SOCIAL_AUTH_FACEBOOK_SCOPE` to get extra permissions from facebook. Email is not sent by default, to get it, you must request the `email` permission: ```default SOCIAL_AUTH_FACEBOOK_SCOPE = ['email'] ``` - Define `SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS` to pass extra parameters to [https://graph.facebook.com/me](https://graph.facebook.com/me) when gathering the user profile data (you need to explicitly ask for fields like `email` using `fields` key): ```default SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'locale': 'ru_RU', 'fields': 'id, name, email, age_range' } ``` If you define a redirect URL in Facebook setup page, be sure to not define [http://127.0.0.1:8000](http://127.0.0.1:8000) or [http://localhost:8000](http://localhost:8000) because it won’t work when testing. Instead I define [http://myapp.com](http://myapp.com) and setup a mapping on `/etc/hosts`. Currently the backend uses Facebook API version 18.0 by default, but this can be overridden by the following setting: ```default SOCIAL_AUTH_FACEBOOK_API_VERSION = '19.0' ``` #### NOTE If you’re using Facebook Graph API v3.0 or later, be aware that several parameters have been deprecated: - The `display` parameter (e.g., `{'display': 'touch'}`) is no longer supported. Facebook now automatically detects mobile devices based on the user agent. - Make sure to check Facebook’s [Graph API Changelog](https://developers.facebook.com/docs/graph-api/changelog) for other deprecated features when upgrading to newer API versions. ## Canvas Application If you need to perform authentication from Facebook Canvas application: - Create your canvas application at [http://developers.facebook.com/apps](http://developers.facebook.com/apps) - In Facebook application settings specify your canvas URL `mysite.com/fb` (current default) - Add the Facebook Canvas Application backend to your `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.facebook.FacebookAppOAuth2', ... ) ``` - Setup your Python Social Auth settings and your application namespace: ```default SOCIAL_AUTH_FACEBOOK_APP_KEY = '' SOCIAL_AUTH_FACEBOOK_APP_SECRET = '' SOCIAL_AUTH_FACEBOOK_APP_NAMESPACE = '' ``` - Launch your testing server on port 80 (use sudo or nginx or apache) for browser to be able to load it when Facebook calls canvas URL - Open your Facebook page via [http://apps.facebook.com/app_namespace](http://apps.facebook.com/app_namespace) or better via [http://www.facebook.com/pages/user-name/user-id?sk=app_app-id](http://www.facebook.com/pages/user-name/user-id?sk=app_app-id) - After that you will see this page in a right way and will able to connect to application and login automatically after connection - Provide a template to be rendered, it must have this JavaScript snippet (or similar) in it: ```default ``` More info on the topic at [Facebook Canvas Application Authentication](http://www.ikrvss.ru/2011/09/22/django-social-auth-and-facebook-canvas-applications/). # backends/facebook_limited_login.html.md # Facebook Limited Login ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |--------------------------|--------------------------------------------------------------| | `facebook-limited-login` | `social_core.backends.facebook_limited.FacebookLimitedLogin` | [Facebook Limited Login](https://developers.facebook.com/docs/facebook-login/limited-login/) is required by the Facebook iOS SDK. ## App creation Register a new application at [Facebook App Creation](https://developers.facebook.com/apps/creation/), don’t use `localhost` in the `App Domains` and `Site URL` fields as Facebook does not allow this. Instead, use a placeholder like `myapp.com` and define that domain in your `/etc/hosts` or similar file for your OS. For more information see the [hosts file](https://en.wikipedia.org/wiki/Hosts_(file)) article on Wikipedia. ## Configuration Set the `SOCIAL_AUTH_FACEBOOK_LIMITED_LOGIN_KEY` to the value of the `App Id`. This field is required for verifying the Facebook access token received from the iOS SDK. ## Django Configuration Set the Facebook Limited Login Key in `settings.py`: ```python SOCIAL_AUTH_FACEBOOK_LIMITED_LOGIN_KEY = "{app_id}" ``` Enable the auth backend: ```python AUTHENTICATION_BACKENDS = ( ... "social_core.backends.facebook_limited.FacebookLimitedLogin", ... ) ``` # backends/fedora.html.md # Fedora ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------------------| | `fedora-oidc` | `social_core.backends.fedora.FedoraOpenIdConnect` | | `fedora` | `social_core.backends.fedora.FedoraOpenId` | Fedora’s OpenID Connect (OIDC) backend requires the following minimum configuration: ```default SOCIAL_AUTH_FEDORA_OIDC_KEY = '' SOCIAL_AUTH_FEDORA_OIDC_SECRET = '' ``` ## Scopes The default scopes will include the user’s group and agreements. You can request additional claims, for example: ```default SOCIAL_AUTH_FEDORA_OIDC_SCOPE = ['groups'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_FEDORA_OIDC_IGNORE_DEFAULT_SCOPE = True ``` ## Environment You can override the location of the OIDC provider with the `SOCIAL_AUTH_FEDORA_OIDC_OIDC_ENDPOINT` setting. For example, to authenticate with Fedora’s staging environment, use this setting: ```default SOCIAL_AUTH_FEDORA_OIDC_OIDC_ENDPOINT = 'https://id.stg.fedoraproject.org' ``` # backends/fitbit.html.md # Fitbit ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `fitbit` | `social_core.backends.fitbit.FitbitOAuth1` | | `fitbit` | `social_core.backends.fitbit.FitbitOAuth2` | Fitbit supports both OAuth 2.0 and OAuth 1.0a logins. OAuth 2 is preferred for new integrations, as OAuth 1.0a does not support getting heartrate or location and will be deprecated in the future. 1. Register a new OAuth Consumer [here](https://dev.fitbit.com/apps/new) 2. Configure the appropriate settings for OAuth 2.0 or OAuth 1.0a (see below). ## OAuth 2.0 or OAuth 1.0a - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_FITBIT_KEY = '' SOCIAL_AUTH_FITBIT_SECRET = '' ``` ## OAuth 2.0 specific settings By default, only the `profile` scope is requested. To request more scopes, set SOCIAL_AUTH_FITBIT_SCOPE: ```default SOCIAL_AUTH_FITBIT_SCOPE = [ 'activity', 'heartrate', 'location', 'nutrition', 'profile', 'settings', 'sleep', 'social', 'weight' ] ``` The above will request all permissions from the user. # backends/flat.html.md # Flat ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `flat` | `social_core.backends.flat.FlatOAuth2` | [Flat](https://flat.io) uses OAuth2. In order to enable the backend follow: - On your project settings, you should add Flat on your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.flat.FlatOAuth2', ) ``` - Register an application at [Flat Developer Portal](https://flat.io/developers) - Fill in the **Client Id** and **Client Secret** values in your settings: ```default SOCIAL_AUTH_FLAT_KEY = '' SOCIAL_AUTH_FLAT_SECRET = '' ``` - Set the `Callback URL` to `http:///complete/flat/` - Specify [scopes](https://flat.io/developers/api/reference/#section/Authentication) with: ```default SOCIAL_AUTH_FLAT_SCOPE = [...] ``` # backends/flickr.html.md # Flickr ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `flickr` | `social_core.backends.flickr.FlickrOAuth` | Flickr uses OAuth v1.0 for authentication. - Register a new application at the [Flickr App Garden](http://www.flickr.com/services/apps/create/), and - fill `Key` and `Secret` values in the settings: ```default SOCIAL_AUTH_FLICKR_KEY = '' SOCIAL_AUTH_FLICKR_SECRET = '' ``` - Flickr might show a messages saying “Oops! Flickr doesn’t recognise the permission set.”, if encountered with this error, just define this setting: ```default SOCIAL_AUTH_FLICKR_AUTH_EXTRA_ARGUMENTS = {'perms': 'read'} ``` # backends/foursquare.html.md # Foursquare ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `foursquare` | `social_core.backends.foursquare.FoursquareOAuth2` | Foursquare uses OAuth2. In order to enable the backend follow: - Register an application at [Foursquare Developers Portal](https://foursquare.com/developers/register), set the `Redirect URI` to `http:///complete/foursquare/` - Fill in the **Client Id** and **Client Secret** values in your settings: ```default SOCIAL_AUTH_FOURSQUARE_KEY = '' SOCIAL_AUTH_FOURSQUARE_SECRET = '' ``` # backends/gitea.html.md # Gitea ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `gitea` | `social_core.backends.gitea.GiteaOAuth2` | Gitea supports OAuth2 protocol. - Register a new application at [Gitea Applications](https://gitea.com/user/settings/applications). - Set the callback URL to `http://example.com/complete/gitea/` replacing `example.com` with your domain. Drop the trailing slash if the project doesn’t use it, the URL **must** match the value sent. - Fill the `Client ID` and `Client Secret` values from Gitea in the settings: ```default SOCIAL_AUTH_GITEA_KEY = '' SOCIAL_AUTH_GITEA_SECRET = '' ``` If your Gitea setup resides in another domain, then add the following setting: ```default SOCIAL_AUTH_GITEA_API_URL = 'https://example.com' ``` it must be the **full url** to your Gitea setup. # backends/github.html.md # GitHub ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------------| | `github` | `social_core.backends.github.GithubOAuth2` | | `github-org` | `social_core.backends.github.GithubOrganizationOAuth2` | | `github-team` | `social_core.backends.github.GithubTeamOAuth2` | | `github-app` | `social_core.backends.github.GithubAppAuth` | GitHub works similar to Facebook (OAuth). - On your project settings, you should add Github on your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.github.GithubOAuth2', ) ``` - Register a new application at [GitHub Developers](https://github.com/settings/applications/new), set the callback URL to `http://example.com/complete/github/` replacing `example.com` with your domain. This will generate a Client Key and a Client Secret. - Add these values of `Client ID` and `Client Secret` from GitHub in your project settings file. The `Client ID` should be added on `SOCIAL_AUTH_GITHUB_KEY` and the `Client Secret` should be added on `SOCIAL_AUTH_GITHUB_SECRET`: ```default SOCIAL_AUTH_GITHUB_KEY = 'a1b2c3d4' SOCIAL_AUTH_GITHUB_SECRET = 'e5f6g7h8i9' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_GITHUB_SCOPE = [...] ``` ## GitHub for Organizations When defining authentication for organizations, use the `GithubOrganizationOAuth2` backend instead. The settings are the same as the non-organization backend, but the names must be: ```default SOCIAL_AUTH_GITHUB_ORG_* ``` Be sure to define the organization name using the setting: ```default SOCIAL_AUTH_GITHUB_ORG_NAME = '' ``` This name will be used to check that the user really belongs to the given organization and discard it if they’re not part of it. ## GitHub for Teams Similar to `GitHub for Organizations`, there’s a GitHub for Teams backend, use the backend `GithubTeamOAuth2`. The settings are the same as the basic backend, but the names must be: ```default SOCIAL_AUTH_GITHUB_TEAM_* ``` Be sure to define the `Team ID` using the setting: ```default SOCIAL_AUTH_GITHUB_TEAM_ID = '' ``` This `id` will be used to check that the user really belongs to the given team and discard it if they’re not part of it. ## GitHub for Enterprises Check the docs [Backend classes](backends/github_enterprise.html.md#github-enterprise) if planning to use GitHub Enterprises. ## GitHub Apps Similar to the `GithubOAuth2` backend but primarily intended for use with GitHub applications (non-oauth application type). For GitHub App applications there are two primary workflows: 1. A person clicks on an icon/button on your website and initiates the OAuth login procedure. They will be redirected to GitHub to complete the process and then back to your website. The person should be logged-in automatically. This is the same workflow as with standard OAuth GitHub apps. 2. A person visits your GitHub App public URL, e.g. `https://github.com/apps/my-app`. They click the **Install** button, select onto which account/organization and repositori(es) to install your application and finish the process. GitHub will start sending webhooks to the URL you have configured! It will also redirect the person to `Setup URL (optional)`. - Create a new GitHub App application owned by your organization. e.g. `https://github.com/organizations/python-social-auth/settings/apps/new` - Set `User authorization callback URL` to `http://example.com/complete/github/` replacing `example.com` with your domain. - Turn on `Request user authorization (OAuth) during installation` if you wish to make `Setup URL` equal to `User authorization callback URL`. The side-effect of this is that after installing your GitHub app the person will be redirected back to your website and logged in automatically. When this is turned on steps 2) and 1) above are executed in sequence. - Add the values of `Client ID` and `Client Secret` from GitHub in your project settings file as shown above. # backends/github_enterprise.html.md # Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |--------------------------|-----------------------------------------------------------------------------| | `github-enterprise` | `social_core.backends.github_enterprise.GithubEnterpriseOAuth2` | | `github-enterprise-org` | `social_core.backends.github_enterprise.GithubEnterpriseOrganizationOAuth2` | | `github-enterprise-team` | `social_core.backends.github_enterprise.GithubEnterpriseTeamOAuth2` | ## GitHub Enterprise GitHub Enterprise works similar to regular GitHub, which is in turn based on Facebook (OAuth). - Register a new application on your instance of [GitHub Enterprise Developers](https:///settings/applications/new), set the callback URL to `http://example.com/complete/github-enterprise/` replacing `example.com` with your domain. - Set the URL for your GitHub Enterprise appliance: > SOCIAL_AUTH_GITHUB_ENTERPRISE_URL = ‘[https://git.example.com/](https://git.example.com/)’ - Set the API URL for your GitHub Enterprise appliance: > SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL = ‘[https://git.example.com/api/v3/](https://git.example.com/api/v3/)’ - Fill the `Client ID` and `Client Secret` values from GitHub in the settings: > SOCIAL_AUTH_GITHUB_ENTERPRISE_KEY = ‘Client_ID’ > SOCIAL_AUTH_GITHUB_ENTERPRISE_SECRET = ‘Client_Secret’ - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_GITHUB_ENTERPRISE_SCOPE = [...] ``` # GitHub Enterprise for Organizations When defining authentication for organizations, use the `GithubEnterpriseOrganizationOAuth2` backend instead. The settings are the same as the non-organization backend, but the names must be: ```default SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_* ``` Be sure to define the organization name using the setting: ```default SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_NAME = '' ``` This name will be used to check that the user really belongs to the given organization and discard it if they’re not part of it. # GitHub Enterprise for Teams Similar to `GitHub Enterprise for Organizations`, there’s a GitHub for Teams backend, use the backend `GithubEnterpriseTeamOAuth2`. The settings are the same as the basic backend, but the names must be: ```default SOCIAL_AUTH_GITHUB_ENTERPRISE_TEAM_* ``` Be sure to define the `Team ID` using the setting: ```default SOCIAL_AUTH_GITHUB_ENTERPRISE_TEAM_ID = '' ``` This `id` will be used to check that the user really belongs to the given team and discard it if they’re not part of it. # backends/gitlab.html.md # GitLab ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `gitlab` | `social_core.backends.gitlab.GitLabOAuth2` | GitLab supports OAuth2 protocol. - Register a new application at [GitLab Applications](https://gitlab.com/-/profile/applications). - Set the callback URL to `http://example.com/complete/gitlab/` replacing `example.com` with your domain. Drop the trailing slash if the project doesn’t use it, the URL **must** match the value sent. - Ensure to mark the `read_user` scope. If marking `api` scope too, define: ```default SOCIAL_AUTH_GITLAB_SCOPE = ['api'] ``` - Fill the `Client ID` and `Client Secret` values from GitLab in the settings: ```default SOCIAL_AUTH_GITLAB_KEY = '' SOCIAL_AUTH_GITLAB_SECRET = '' ``` If your GitLab setup resides in another domain, then add the following setting: ```default SOCIAL_AUTH_GITLAB_API_URL = 'https://example.com' ``` it must be the **full url** to your GitLab setup. ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. When `SOCIAL_AUTH_GITLAB_GROUPS_ENABLED = True`, the backend automatically requests `read_api` unless the requested scopes already contain `read_api` or `api`. Enable the corresponding scope in your GitLab OAuth application alongside `read_user`; `read_user` alone cannot retrieve memberships. # backends/google.html.md # Google ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |-----------------|---------------------------------------------------| | `google-oauth2` | `social_core.backends.google.GoogleOAuth2` | | `google-oauth` | `social_core.backends.google.GoogleOAuth` | | `google-onetap` | `social_core.backends.google_onetap.GoogleOneTap` | This section describes how to setup the different services provided by Google. ## Google OAuth #### ATTENTION **Google OAuth deprecation** Important: OAuth 1.0 was officially deprecated on April 20, 2012, and will be shut down on April 20, 2015. We encourage you to migrate to any of the other protocols. Google provides `Consumer Key` and `Consumer Secret` keys to registered applications, but also allows unregistered application to use their authorization system with, but beware that this method will display a security banner to the user telling that the application is not trusted. Check [Google OAuth](http://code.google.com/apis/accounts/docs/OAuth.html) and make your choice. - fill `Consumer Key` and `Consumer Secret` values: ```default SOCIAL_AUTH_GOOGLE_OAUTH_KEY = '' SOCIAL_AUTH_GOOGLE_OAUTH_SECRET = '' ``` anonymous values will be used if not configured as described in their [OAuth reference](http://code.google.com/apis/accounts/docs/OAuth_ref.html#SigningOAuth) - setup any needed extra scope in: ```default SOCIAL_AUTH_GOOGLE_OAUTH_SCOPE = [...] ``` ## Google OAuth2 Recently Google launched OAuth2 support following the definition at OAuth2 draft. It works in a similar way to plain OAuth mechanism, but developers **must** register an application and apply for a set of keys. Check [Google OAuth2](http://code.google.com/apis/accounts/docs/OAuth2.html) document for details. ### IdP Setup To configure Google OAuth2: 1. Go to the [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select an existing one 3. Navigate to **APIs & Services** > **Credentials** 4. Click **Create Credentials** > **OAuth client ID** 5. Configure: * **Application type**: Web application * **Authorized redirect URIs**: `https://your-domain.com/complete/google-oauth2/` 6. Note the **Client ID** and **Client Secret** 7. Configure the **OAuth consent screen** (`APIs & Services > OAuth consent screen`): * Set the **PRODUCT NAME** and other required fields * Add scopes: `email`, `profile`, `openid` ### Application Configuration Fill in `Client ID` and `Client Secret` settings with values from Google: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '' SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '' ``` - setup any needed extra scope: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [...] ``` Check which applications can be included in their [Google Data Protocol Directory](http://code.google.com/apis/gdata/docs/directory.html) To allow user selecting Google account to use, add the `prompt` parameter with `select_account` value: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {'prompt': 'select_account'} ``` To restrict authentication to specific domains (useful for G Suite/Google Workspace organizations), use domain whitelisting. Check the [whitelists](../configuration/settings.html#whitelists) settings for details. ## Google One Tap [Google One Tap](https://developers.google.com/identity/gsi/web/guides/features) is a bit different from the OAuth2 flow as the login process is started on the client side. Because of this start url is not available, only a complete one. * Additional dependencies are needed, these will be automatically installed by the `google-onetap` extra, for example: `uv pip install 'social-core[google-onetap]`. * To enable the backend create an application using the [Google console](https://code.google.com/apis/console) to retrieve your Google Client ID. Make sure sure to add your website’s URL to `Authorized JavaScript origins` and `Authorized redirect URIs` (don’t forget to also include the port number if you are using localhost). * Fill in the key setting looking inside the Google console the subsection `Credentials` inside `API & auth`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.google_onetap.GoogleOneTap', ) SOCIAL_AUTH_GOOGLE_ONETAP_KEY = '...' SOCIAL_AUTH_GOOGLE_ONETAP_IGNORE_MISSING_CSRF_COOKIE = True / False ``` `SOCIAL_AUTH_GOOGLE_ONETAP_KEY` corresponds to the variable `CLIENT ID`. `SOCIAL_AUTH_GOOGLE_ONETAP_IGNORE_MISSING_CSRF_COOKIE` disabled the CSRF checks if the token is missing from the cookies. This is an optional setting because the cookie is not being set if authentication process started on a different domain (for more details check out the [related issue](https://issuetracker.google.com/issues/226157137)). * Add the [One Tap snippet](https://developers.google.com/identity/gsi/web/guides/display-google-one-tap) to your page: ```default
``` * And [load the client library](https://developers.google.com/identity/gsi/web/guides/client-library): ```default ``` ## Orkut As of September 30, 2014, Orkut has been [shut down](https://support.google.com/orkut/?csw=1#Authenticating). ## User identification Google OAuth2, OpenID Connect, and One Tap use the stable `sub` claim for account association. The legacy OAuth1 backend uses Google’s stable `id`. Associations created by older social-core releases used the email address and migrate to the stable identifier on the next successful authentication. The following legacy settings remain accepted, but stable identifiers are now the default: ```default SOCIAL_AUTH_GOOGLE_OAUTH_USE_UNIQUE_USER_ID = True ``` or: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_USE_UNIQUE_USER_ID = True ``` depending on the backends in use. See [Configurable User ID Key](../configuration/settings.html#configurable-user-id-key) for migration controls and custom identifier settings. ## Refresh Tokens To get an OAuth2 refresh token along with the access token, you must pass an extra argument: `access_type=offline`. To do this with Google OAuth2: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = { 'access_type': 'offline' } ``` # backends/grafana.html.md # Grafana ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `grafana` | `social_core.backends.grafana.GrafanaOAuth2` | Grafana works similar to Facebook (OAuth). - On your project settings, you should add Grafana on your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.grafana.GrafanaOAuth2', ) ``` - Register a new application at Grafana Cloud Portal in grafana.com by doing My Account → SECURITY → OAuth Clients → Add OAuth Client Application. Set any name and in URL just the domain, without any path. - Copy client_id and client_secret and add these values in your project settings file. The `client_id` should be added on `SOCIAL_AUTH_GRAFANA_KEY` and the `client_secret` should be added on `SOCIAL_AUTH_GRAFANA_SECRET`: ```default SOCIAL_AUTH_GRAFANA_KEY = 'a1b2c3d4' SOCIAL_AUTH_GRAFANA_SECRET = 'e5f6g7h8i9' ``` - The default scope is ``['profile', 'email']`` but it’s possible to define it in settings with: ```default SOCIAL_AUTH_GRAFANA_SCOPE = [...] ``` # backends/helmholtz.html.md # Helmholtz AAI (OpenID Connect) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------------------------| | `helmholtz` | `social_core.backends.helmholtz.HelmholtzOpenIdConnect` | The Helmholtz backend allows authentication against the [Helmholtz AAI](https://hifis.net/aai/), the authentication and authorization infrastructure of the Helmholtz Association operated by [HIFIS](https://hifis.net). To obtain a client id and secret, and for the requested scopes to be released, you have to register your service with the OP. See the [Helmholtz AAI documentation](https://hifis.net/doc/helmholtz-aai/) for details. A minimum configuration is: ```default SOCIAL_AUTH_HELMHOLTZ_KEY = '' SOCIAL_AUTH_HELMHOLTZ_SECRET = '' ``` The remaining configuration is auto-detected by fetching: ```default https://login.helmholtz.de/oauth2/.well-known/openid-configuration ``` ## Username The backend reads the username from the `preferred_username` claim returned by the server. If the username is under a different key, this can be overridden: ```default SOCIAL_AUTH_HELMHOLTZ_USERNAME_KEY = 'nickname' ``` This setting indicates that the username should be populated from the `nickname` claim instead. ## Scopes By default the backend requests, besides `openid`, `profile` and `email`, the scopes `voperson_id`, `eduperson_entitlement`, `eduperson_scoped_affiliation`, `voperson_external_affiliation` and `eduperson_assurance`. You can request additional scopes, for example: ```default SOCIAL_AUTH_HELMHOLTZ_SCOPE = ['display_name'] ``` ## Restricting access by entitlement Access to the service can be restricted to users holding certain entitlements (typically representing membership in a virtual organization): ```default SOCIAL_AUTH_HELMHOLTZ_ALLOWED_ENTITLEMENTS = [ 'urn:geant:helmholtz.de:group:my-vo#login.helmholtz.de', ] ``` A user holding any of the listed entitlements is allowed to log in. If the list is empty (the default), all users are allowed. The entitlements are read from the `eduperson_entitlement` claim. If your deployment provides them under a different claim, this can be overridden: ```default SOCIAL_AUTH_HELMHOLTZ_ENTITLEMENT_KEY = 'entitlement' ``` # backends/implementation.html.md # Adding a new backend Adding new backends is quite easy. Usually just all that’s required is to add a `class` with a couple of settings and method overrides to retrieve user data from a services API. Follow the details below: ## Common attributes First, let’s check the common attributes for all backend types. `name = ''` : Any backend needs a name, usually the popular name of the service is used, like `facebook`, `twitter`, etc. It must be unique, otherwise another backend can take precedence if it’s listed before in the `AUTHENTICATION_BACKENDS` setting. `ID_KEY = None` : For mapping-based backends, defines the field in the service response that identifies the user as unique to the service. The value is later stored in the `uid` attribute in the `UserSocialAuth` instance. This can be overridden per-backend via the `SOCIAL_AUTH__ID_KEY` setting (see [Configurable User ID Key](../configuration/settings.html#configurable-user-id-key)). `REQUIRES_EMAIL_VALIDATION = False` : Flags the backend to enforce email validation during the pipeline (if the corresponding pipeline `social_core.pipeline.mail.mail_validation` was enabled). `EXTRA_DATA = None` : During the auth process some basic user data is returned by the provider or retrieved by the `user_data()` method which usually is used to call some API on the provider to retrieve it. This data will be stored in the `UserSocialAuth.extra_data` attribute, but to make it accessible under some common names on different providers, this attribute defines a list of tuples in the form `(name, alias)` where `name` is the key in the user data (which should be a `dict` instance) and `alias` is the name to store it on `extra_data`. `ACCESS_TOKEN_METHOD = 'GET'` : Specifying the method type required to retrieve your access token if it’s not the default GET request. ## Initiating authentication Framework integrations that have the current local user can pass it to `social_core.actions.do_auth(backend, user=current_user)`. The optional `user` argument is passed to `BaseAuth.prepare_auth(user=None)` after the normal redirect and session-field handling, immediately before `start()`. The default hook does nothing, so integrations that omit the user retain the existing behavior. Backends can override `prepare_auth()` to validate the local user or prepare backend-specific state before authentication starts. An exception from the hook stops initiation. The user object is passed only to the hook; a backend that needs to bind a later callback to the user must decide whether and how to persist a stable identifier. ## OAuth OAuth1 and OAuth2 provide some common definitions based on the shared behavior during the auth process. For example, a successful API response from `AUTHORIZATION_URL` usually returns some basic user data like a user Id. ### Shared attributes `name` : This defines the backend name and identifies it during the auth process. The name is used in the URLs `/login/` and `/complete/`. `ID_KEY = 'id'` : The default key name where the user identification field is defined, it’s used in the auth process when some basic user data is returned. This Id is stored in the `UserSocialAuth.uid` field and this, together with the `UserSocialAuth.provider` field, is used to uniquely identify a user association. `SCOPE_PARAMETER_NAME = 'scope'` : The scope argument is used to tell the provider the API endpoints you want to call later, it’s a permissions request granted over the `access_token` later retrieved. The default value is `scope` since that’s usually the name used in the URL parameter, but can be overridden if needed. `DEFAULT_SCOPE = None` : Some providers give nothing about the user but some basic data like the user Id or an email address. The default scope attribute is used to specify a default value for the `scope` argument to request those extra bits. `SCOPE_SEPARATOR = ' '` : The `scope` argument is usually a list of permissions to request, the list is joined with a separator, usually just a blank space, but this can differ from provider to provider. Override the default value with this attribute if it differs. ### OAuth2 OAuth2 backends are fairly simple to implement; just a few settings, a method override and it’s mostly ready to go. The key points on these backends are: `AUTHORIZATION_URL` : This is the entry point for the authorization mechanism, users must be redirected to this URL, used on `auth_url` method which builds the redirect address with `AUTHORIZATION_URL` plus some arguments (`client_id`, `redirect_uri`, `response_type`, and `state`). `ACCESS_TOKEN_URL` : Must point to the API endpoint that provides an `access_token` needed to authenticate in users behalf on future API calls. `REFRESH_TOKEN_URL` : Some providers give the option to renew the `access_token` since they are usually limited in time, once that time runs out, the token is invalidated and cannot be used anymore. This attribute should point to that API endpoint. `get_refresh_token(extra_data) -> str | None` : Selects the stored credential passed to `refresh_token()`. The default implementation returns a nonempty string from `extra_data['refresh_token']` or `None` when it is unavailable. Custom backends that renew by exchanging an access token must override this hook; storage no longer falls back to the access token automatically. For example:
```default def get_refresh_token(self, extra_data): token = extra_data.get('access_token') return token if isinstance(token, str) and token else None ```
This selects the credential only. The backend’s `refresh_token_params()` must still construct the provider’s required exchange request. Facebook uses this hook with its `fb_exchange_token` grant. See [Token renewal](backends/oauth.html.md#oauth-token-renewal) for missing-credential behavior. `RESPONSE_TYPE` : The response type expected on the auth process, default value is `code` as dictated by OAuth2 definition. Override it if default value doesn’t fit the provider implementation. `STATE_PARAMETER` : OAuth2 defines that a `state` parameter can be passed in order to validate the process, it’s kind of a CSRF check to avoid man in the middle attacks. Some don’t recognise it or don’t return it which will make the auth process invalid. Set this attribute to `False` in that case. `REDIRECT_STATE` : For those providers that don’t recognise the `state` parameter, the app can add a `redirect_state` argument to the `redirect_uri` to mimic it. Set this value to `False` if the provider likes to verify the `redirect_uri` value and this parameter invalidates that check. Example code: ```default from social_core.backends.oauth import BaseOAuth2 class GitHubOAuth2(BaseOAuth2): """GitHub OAuth authentication backend""" name = 'github' AUTHORIZATION_URL = 'https://github.com/login/oauth/authorize' ACCESS_TOKEN_URL = 'https://github.com/login/oauth/access_token' ACCESS_TOKEN_METHOD = 'POST' SCOPE_SEPARATOR = ',' EXTRA_DATA = [ ('id', 'id'), ('expires', 'expires') ] def get_user_details(self, response): """Return user details from GitHub account""" return {'username': response.get('login'), 'email': response.get('email') or '', 'fullname': response.get('name')} def user_data(self, access_token, *args, **kwargs): """Loads user data from service""" url = 'https://api.github.com/user?' + urlencode({ 'access_token': access_token }) return self.get_json(url) ``` ### OAuth2 with PKCE This is simply an extension of OAuth2 adding [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) which provides security against authorization code interception attack. Use the `BaseOAuth2PKCE` class as a drop-in replacement for `BaseOAuth2` for implementing backends that support PKCE. For reference, you may refer to [Bitbucket Data Center OAuth2](https://github.com/python-social-auth/social-core/blob/master/social_core/backends/bitbucket_datacenter.py) and [Twitter OAuth2](https://github.com/python-social-auth/social-core/blob/master/social_core/backends/twitter_oauth2.py) as example implementations. Only a single key attribute is needed on these backends: `PKCE_DEFAULT_CODE_CHALLENGE_METHOD` : Depends on which code challenge method is supported by the provider. The possible values for this are `s256` and `plain`. By default, `s256` is set. ### OAuth1 OAuth1 process is a bit more trickier, [Twitter Docs](https://dev.twitter.com/docs/auth/implementing-sign-twitter) explains it quite well. Besides the `AUTHORIZATION_URL` and `ACCESS_TOKEN_URL` attributes, a third one is needed used when starting the process. `REQUEST_TOKEN_URL = ''` : During the auth process an unauthorized token is needed to start the process, later this token is exchanged for an `access_token`. This setting points to the API endpoint where that unauthorized token can be retrieved. Example code: ```default from xml.dom import minidom from social_core.backends.oauth import ConsumerBasedOAuth class TripItOAuth(ConsumerBasedOAuth): """TripIt OAuth authentication backend""" name = 'tripit' AUTHORIZATION_URL = 'https://www.tripit.com/oauth/authorize' REQUEST_TOKEN_URL = 'https://api.tripit.com/oauth/request_token' ACCESS_TOKEN_URL = 'https://api.tripit.com/oauth/access_token' EXTRA_DATA = [('screen_name', 'screen_name')] def get_user_details(self, response): """Return user details from TripIt account""" return {'username': response['screen_name'], 'email': response['email'], 'fullname': response['name']} def user_data(self, access_token, *args, **kwargs): """Return user data provided""" url = 'https://api.tripit.com/v1/get/profile' request = self.oauth_request(access_token, url) content = self.fetch_response(request) try: dom = minidom.parseString(content) except ValueError: return None return { 'id': dom.getElementsByTagName('Profile')[0].getAttribute('ref'), 'name': dom.getElementsByTagName( 'public_display_name')[0].childNodes[0].data, 'screen_name': dom.getElementsByTagName( 'screen_name')[0].childNodes[0].data, 'email': dom.getElementsByTagName( 'is_primary')[0].parentNode.getElementsByTagName( 'address')[0].childNodes[0].data, } ``` ## OpenID OpenID is far simpler than OAuth since it’s used for authentication rather than authorization (regardless it’s used for authorization too). A single attribute is usually needed, the authentication URL endpoint. `URL = ''` : OpenID endpoint where to redirect the user. Sometimes the URL is user dependent, like in [myOpenID](https://www.myopenid.com/) where the URL is `https://.myopenid.com`. For those cases where the user must input it’s handle (or full URL). The backend must override the `openid_url()` method to retrieve it and return a full URL to where the user will be redirected. Example code: ```default from social_core.backends.open_id import OpenIdAuth from social_core.exceptions import AuthInputError class LiveJournalOpenId(OpenIdAuth): """LiveJournal OpenID authentication backend""" name = 'livejournal' def get_user_details(self, response): """Generate username from identity url""" values = super(LiveJournalOpenId, self).get_user_details(response) values['username'] = values.get('username') or \ urlparse.urlsplit(response.identity_url)\ .netloc.split('.', 1)[0] return values def openid_url(self): """Returns LiveJournal authentication URL""" if not self.data.get('openid_lj_user'): raise AuthInputError(self, code="missing_parameter", parameter="openid_lj_user", stage="begin") return 'http://%s.livejournal.com' % self.data['openid_lj_user'] ``` ## Auth APIs For others authentication types, a `BaseAuth` class is defined to help. Those custom auth methods must override the `auth_url()` and `auth_complete()` methods. Example code: ```default from google.appengine.api import users from social_core.backends.base import BaseAuth from social_core.exceptions import AuthUnknownError class GoogleAppEngineAuth(BaseAuth): """GoogleAppengine authentication backend""" name = 'google-appengine' def get_user_id(self, details, response): """Return current user id.""" user = users.get_current_user() if user: return user.user_id() def get_user_details(self, response): """Return user basic information (id and email only).""" user = users.get_current_user() return {'username': user.user_id(), 'email': user.email(), 'fullname': '', 'first_name': '', 'last_name': ''} def auth_url(self): """Build and return complete URL.""" return users.create_login_url(self.redirect_uri) def auth_complete(self, *args, **kwargs): """Completes login process, must return user instance.""" if not users.get_current_user(): raise AuthUnknownError(self, code="unknown_error", stage="callback") kwargs.update({'response': '', 'backend': self}) return self.strategy.authenticate(*args, **kwargs) ``` ## Common backend methods All backends inherit from `BaseAuth` which provides several methods that can be overridden to customize behavior. Here are some key methods: `process_error(data, *, stage="callback")` : Detects provider errors in callbacks and successful HTTP responses. OAuth2 backends also call this hook during token exchange and refresh. Overrides must accept the keyword-only `stage` argument, pass it to the superclass, and use it when constructing structured exceptions. See [Exceptions](exceptions.html.md). `id_key()` : Returns the ID key to use for this backend. By default, this method checks if the `ID_KEY` has been configured via settings (using `SOCIAL_AUTH__ID_KEY`) and returns that value if present, otherwise it falls back to the `ID_KEY` class attribute.
Most backends should not need to override this method unless they have special logic for determining the ID key. Instead, use the `SOCIAL_AUTH__ID_KEY` setting to configure it. `get_user_id(details, response)` : Returns a unique ID for the current user from the provider’s response or from the details dict. This method uses `id_key()` to determine which field to extract from the response. The default implementation checks both `details` and `response` dicts for the configured ID key.
Override this method if you need custom logic for extracting the user ID, such as reading a nested object, combining multiple fields, or performing transformations. Mapping-based overrides must use `id_key()` for the selectable leaf field while retaining any required scoping or validation.
Example of custom user ID retrieval:
```default def get_user_id(self, details, response): """Custom user ID retrieval""" user_id = self.get_user_id_from_sources(response.get("user")) return f"{response['tenant']}:{user_id}" ```
If a backend retains an older identifier selector, an explicitly configured `ID_KEY` should take precedence and the older setting should be used only when `ID_KEY` is unset.
Protocol-derived identifiers do not always correspond to a mapping field. For example, generic OpenID and Steam use a validated identity URL, while SAML uses its per-IdP permanent-ID mapping. Such backends may intentionally ignore `ID_KEY`, but the behavior must be documented by the backend. `get_user_details(response)` : Extracts user details (username, email, first_name, last_name, fullname) from the provider’s API response. This method should return a dictionary with the extracted values. Return provider-supplied names without splitting or joining them; the `social_names` pipeline step performs [Name normalization](pipeline.html.md#name-normalization). `BaseAuth.get_user_names()` is deprecated. # backends/index.html.md # Backends Here’s a list and detailed instructions on how to set up the support for each backend. ## Adding new backend support Add new backends is quite easy, usually adding just a `class` with a couple methods overrides to retrieve user data from services API. Follow the details in the *Implementation* docs. * [Adding a new backend](backends/implementation.html.md) * [Common attributes](backends/implementation.html.md#common-attributes) * [Initiating authentication](backends/implementation.html.md#initiating-authentication) * [OAuth](backends/implementation.html.md#oauth) * [OpenID](backends/implementation.html.md#openid) * [Auth APIs](backends/implementation.html.md#auth-apis) * [Common backend methods](backends/implementation.html.md#common-backend-methods) ## Supported backends Here’s the list of currently supported backends. ### Non-social backends * [Email Auth](backends/email.html.md) * [Backend class](backends/email.html.md#backend-class) * [Backend settings](backends/email.html.md#backend-settings) * [Email validation](backends/email.html.md#email-validation) * [Password handling](backends/email.html.md#password-handling) * [Username Auth](backends/username.html.md) * [Backend class](backends/username.html.md#backend-class) * [Backend settings](backends/username.html.md#backend-settings) * [Password handling](backends/username.html.md#password-handling) ### Base OAuth and OpenID classes * [OAuth](backends/oauth.html.md) * [Token renewal](backends/oauth.html.md#token-renewal) * [OpenID](backends/openid.html.md) * [Backend class](backends/openid.html.md#backend-class) * [Username](backends/openid.html.md#username) * [SAML](backends/saml.html.md) * [Backend class](backends/saml.html.md#backend-class) * [Required Dependency](backends/saml.html.md#required-dependency) * [Required Configuration](backends/saml.html.md#required-configuration) * [Basic Usage](backends/saml.html.md#basic-usage) * [Advanced Settings](backends/saml.html.md#advanced-settings) * [Advanced Usage](backends/saml.html.md#advanced-usage) * [Troubleshooting](backends/saml.html.md#troubleshooting) * [External memberships](backends/saml.html.md#external-memberships) ### Social backends * [Amazon](backends/amazon.html.md) * [Backend class](backends/amazon.html.md#backend-class) * [Angel List](backends/angel.html.md) * [Backend class](backends/angel.html.md#backend-class) * [AppleID](backends/apple.html.md) * [Backend class](backends/apple.html.md#backend-class) * [ArcGIS](backends/arcgis.html.md) * [Backend class](backends/arcgis.html.md#backend-class) * [OAuth2](backends/arcgis.html.md#oauth2) * [Auth0](backends/auth0.html.md) * [Backend class](backends/auth0.html.md#backend-class) * [Auth0 OAuth2](backends/auth0.html.md#auth0-oauth2) * [Auth0 OpenID Connect](backends/auth0_openidconnect.html.md) * [Backend class](backends/auth0_openidconnect.html.md#backend-class) * [IdP Setup](backends/auth0_openidconnect.html.md#idp-setup) * [Application Configuration](backends/auth0_openidconnect.html.md#application-configuration) * [Scopes](backends/auth0_openidconnect.html.md#scopes) * [Microsoft Entra ID and Azure AD B2C](backends/azuread.html.md) * [Backend classes](backends/azuread.html.md#backend-classes) * [User identifiers](backends/azuread.html.md#user-identifiers) * [IdP Setup](backends/azuread.html.md#idp-setup) * [Scopes, tokens, and app roles](backends/azuread.html.md#scopes-tokens-and-app-roles) * [Application Configuration](backends/azuread.html.md#application-configuration) * [Authority configuration](backends/azuread.html.md#authority-configuration) * [Proof Key for Code Exchange (PKCE)](backends/azuread.html.md#proof-key-for-code-exchange-pkce) * [Token renewal](backends/azuread.html.md#token-renewal) * [Tenant Support](backends/azuread.html.md#tenant-support) * [B2C Tenant](backends/azuread.html.md#b2c-tenant) * [B2C provider logout](backends/azuread.html.md#b2c-provider-logout) * [External memberships](backends/azuread.html.md#external-memberships) * [Battle.net](backends/battlenet.html.md) * [Backend class](backends/battlenet.html.md#backend-class) * [Behance](backends/behance.html.md) * [Backend class](backends/behance.html.md#backend-class) * [DEPRECATED NOTICE](backends/behance.html.md#deprecated-notice) * [Belgium EID](backends/belgium_eid.html.md) * [Backend class](backends/belgium_eid.html.md#backend-class) * [Bitbucket](backends/bitbucket.html.md) * [Backend class](backends/bitbucket.html.md#backend-class) * [OAuth2](backends/bitbucket.html.md#oauth2) * [OAuth1](backends/bitbucket.html.md#oauth1) * [User ID](backends/bitbucket.html.md#user-id) * [Bitbucket Data Center OAuth2](backends/bitbucket_datacenter_oauth2.html.md) * [Backend class](backends/bitbucket_datacenter_oauth2.html.md#backend-class) * [Configuration](backends/bitbucket_datacenter_oauth2.html.md#configuration) * [Extra Configuration](backends/bitbucket_datacenter_oauth2.html.md#extra-configuration) * [Box.net](backends/box.html.md) * [Backend class](backends/box.html.md#backend-class) * [Bungie](backends/bungie.html.md) * [Backend class](backends/bungie.html.md#backend-class) * [CAS (OpenID Connect via Apereo CAS)](backends/cas.html.md) * [Backend class](backends/cas.html.md#backend-class) * [User identification](backends/cas.html.md#user-identification) * [Username](backends/cas.html.md#username) * [Scopes](backends/cas.html.md#scopes) * [External memberships](backends/cas.html.md#external-memberships) * [CESiD AAI - Czech Educational and Scientific Identification AAI](backends/cesid.html.md) * [Backend class](backends/cesid.html.md#backend-class) * [Scopes](backends/cesid.html.md#scopes) * [Coinbase](backends/coinbase.html.md) * [Backend class](backends/coinbase.html.md#backend-class) * [Cognito](backends/cognito.html.md) * [Backend class](backends/cognito.html.md#backend-class) * [Coursera](backends/coursera.html.md) * [Backend class](backends/coursera.html.md#backend-class) * [DailyMotion](backends/dailymotion.html.md) * [Backend class](backends/dailymotion.html.md#backend-class) * [DigitalOcean](backends/digitalocean.html.md) * [Backend class](backends/digitalocean.html.md#backend-class) * [Discogs](backends/discogs.html.md) * [Backend class](backends/discogs.html.md#backend-class) * [Discord](backends/discord.html.md) * [Backend class](backends/discord.html.md#backend-class) * [Discourse](backends/discourse.html.md) * [Backend class](backends/discourse.html.md#backend-class) * [Using multiple Discourse instances](backends/discourse.html.md#using-multiple-discourse-instances) * [External memberships](backends/discourse.html.md#external-memberships) * [Disqus](backends/disqus.html.md) * [Backend class](backends/disqus.html.md#backend-class) * [Docker](backends/docker.html.md) * [Backend class](backends/docker.html.md#backend-class) * [Docker.io OAuth2](backends/docker.html.md#docker-io-oauth2) * [Douban](backends/douban.html.md) * [Backend class](backends/douban.html.md#backend-class) * [Dribbble](backends/dribbble.html.md) * [Backend class](backends/dribbble.html.md#backend-class) * [Drip](backends/drip.html.md) * [Backend class](backends/drip.html.md#backend-class) * [Dropbox](backends/dropbox.html.md) * [Backend class](backends/dropbox.html.md#backend-class) * [OAuth2 Api V2](backends/dropbox.html.md#oauth2-api-v2) * [Etsy OAuth2](backends/etsy.html.md) * [Backend class](backends/etsy.html.md#backend-class) * [Configuration](backends/etsy.html.md#configuration) * [Extra Configuration](backends/etsy.html.md#extra-configuration) * [Eventbrite OAuth](backends/eventbrite.html.md) * [Backend class](backends/eventbrite.html.md#backend-class) * [EVE Online Single Sign-On (SSO)](backends/eveonline.html.md) * [Backend class](backends/eveonline.html.md#backend-class) * [Evernote OAuth](backends/evernote.html.md) * [Backend classes](backends/evernote.html.md#backend-classes) * [Sandbox](backends/evernote.html.md#sandbox) * [Facebook](backends/facebook.html.md) * [Backend classes](backends/facebook.html.md#backend-classes) * [Token renewal](backends/facebook.html.md#token-renewal) * [OAuth2](backends/facebook.html.md#oauth2) * [Canvas Application](backends/facebook.html.md#canvas-application) * [Facebook Limited Login](backends/facebook_limited_login.html.md) * [Backend class](backends/facebook_limited_login.html.md#backend-class) * [App creation](backends/facebook_limited_login.html.md#app-creation) * [Configuration](backends/facebook_limited_login.html.md#configuration) * [Django Configuration](backends/facebook_limited_login.html.md#django-configuration) * [Fedora](backends/fedora.html.md) * [Backend classes](backends/fedora.html.md#backend-classes) * [Scopes](backends/fedora.html.md#scopes) * [Environment](backends/fedora.html.md#environment) * [Fitbit](backends/fitbit.html.md) * [Backend classes](backends/fitbit.html.md#backend-classes) * [OAuth 2.0 or OAuth 1.0a](backends/fitbit.html.md#oauth-2-0-or-oauth-1-0a) * [OAuth 2.0 specific settings](backends/fitbit.html.md#oauth-2-0-specific-settings) * [Flat](backends/flat.html.md) * [Backend class](backends/flat.html.md#backend-class) * [Flickr](backends/flickr.html.md) * [Backend class](backends/flickr.html.md#backend-class) * [Foursquare](backends/foursquare.html.md) * [Backend class](backends/foursquare.html.md#backend-class) * [GitHub](backends/github.html.md) * [Backend classes](backends/github.html.md#backend-classes) * [GitHub for Organizations](backends/github.html.md#github-for-organizations) * [GitHub for Teams](backends/github.html.md#github-for-teams) * [GitHub for Enterprises](backends/github.html.md#github-for-enterprises) * [GitHub Apps](backends/github.html.md#github-apps) * [Backend classes](backends/github_enterprise.html.md) * [GitHub Enterprise](backends/github_enterprise.html.md#id1) * [GitHub Enterprise for Organizations](backends/github_enterprise.html.md#github-enterprise-for-organizations) * [GitHub Enterprise for Teams](backends/github_enterprise.html.md#github-enterprise-for-teams) * [GitLab](backends/gitlab.html.md) * [Backend class](backends/gitlab.html.md#backend-class) * [External memberships](backends/gitlab.html.md#external-memberships) * [Gitea](backends/gitea.html.md) * [Backend class](backends/gitea.html.md#backend-class) * [Google](backends/google.html.md) * [Backend classes](backends/google.html.md#backend-classes) * [Google OAuth](backends/google.html.md#google-oauth) * [Google OAuth2](backends/google.html.md#google-oauth2) * [Google One Tap](backends/google.html.md#google-one-tap) * [Orkut](backends/google.html.md#orkut) * [User identification](backends/google.html.md#user-identification) * [Refresh Tokens](backends/google.html.md#refresh-tokens) * [Grafana](backends/grafana.html.md) * [Backend class](backends/grafana.html.md#backend-class) * [Helmholtz AAI (OpenID Connect)](backends/helmholtz.html.md) * [Backend class](backends/helmholtz.html.md#backend-class) * [Username](backends/helmholtz.html.md#username) * [Scopes](backends/helmholtz.html.md#scopes) * [Restricting access by entitlement](backends/helmholtz.html.md#restricting-access-by-entitlement) * [Instagram](backends/instagram.html.md) * [Backend class](backends/instagram.html.md#backend-class) * [Just Giving](backends/justgiving.html.md) * [Backend class](backends/justgiving.html.md#backend-class) * [OAuth2](backends/justgiving.html.md#oauth2) * [Kakao](backends/kakao.html.md) * [Backend class](backends/kakao.html.md#backend-class) * [Keycloak - Open Source Red Hat SSO](backends/keycloak.html.md) * [Backend class](backends/keycloak.html.md#backend-class) * [IdP Setup](backends/keycloak.html.md#idp-setup) * [Application Configuration](backends/keycloak.html.md#application-configuration) * [Audience validation](backends/keycloak.html.md#audience-validation) * [Signing key rotation](backends/keycloak.html.md#signing-key-rotation) * [User ID Configuration](backends/keycloak.html.md#user-id-configuration) * [External memberships](backends/keycloak.html.md#external-memberships) * [Kick](backends/kick.html.md) * [Backend class](backends/kick.html.md#backend-class) * [Last.fm](backends/lastfm.html.md) * [Backend class](backends/lastfm.html.md#backend-class) * [Launchpad](backends/launchpad.html.md) * [Backend class](backends/launchpad.html.md#backend-class) * [Lifescience AAI](backends/lifescience.html.md) * [Backend class](backends/lifescience.html.md#backend-class) * [Scopes](backends/lifescience.html.md#scopes) * [Lifescience AAI - (Temporary instance for EOSC node)](backends/lifescience_eosc.html.md) * [Backend class](backends/lifescience_eosc.html.md#backend-class) * [Scopes](backends/lifescience_eosc.html.md#scopes) * [Line.me](backends/line.html.md) * [Backend class](backends/line.html.md#backend-class) * [LinkedIn](backends/linkedin.html.md) * [Backend classes](backends/linkedin.html.md#backend-classes) * [OpenID Connect](backends/linkedin.html.md#openid-connect) * [OAuth2](backends/linkedin.html.md#oauth2) * [LiveJournal](backends/livejournal.html.md) * [Backend class](backends/livejournal.html.md#backend-class) * [MSN Live Connect](backends/live.html.md) * [Backend class](backends/live.html.md#backend-class) * [LoginRadius](backends/loginradius.html.md) * [Backend class](backends/loginradius.html.md#backend-class) * [Lyft](backends/lyft.html.md) * [Backend class](backends/lyft.html.md#backend-class) * [MailChimp](backends/mailchimp.html.md) * [Backend class](backends/mailchimp.html.md#backend-class) * [Mail.ru OAuth](backends/mailru.html.md) * [Backend classes](backends/mailru.html.md#backend-classes) * [Legacy OAuth2 authorization](backends/mailru.html.md#legacy-oauth2-authorization) * [MapMyFitness](backends/mapmyfitness.html.md) * [Backend class](backends/mapmyfitness.html.md#backend-class) * [MediaWiki OAuth1 backend](backends/mediawiki.html.md) * [Backend class](backends/mediawiki.html.md#backend-class) * [Usage](backends/mediawiki.html.md#usage) * [General documentation](backends/mediawiki.html.md#general-documentation) * [Developer documentation](backends/mediawiki.html.md#developer-documentation) * [Code based on](backends/mediawiki.html.md#code-based-on) * [External memberships](backends/mediawiki.html.md#external-memberships) * [Meetup](backends/meetup.html.md) * [Backend class](backends/meetup.html.md#backend-class) * [Mendeley](backends/mendeley.html.md) * [Backend class](backends/mendeley.html.md#backend-class) * [Microsoft Graph](backends/microsoftgraph.html.md) * [Backend class](backends/microsoftgraph.html.md#backend-class) * [MineID](backends/mineid.html.md) * [Backend class](backends/mineid.html.md#backend-class) * [Self-hosted MineID](backends/mineid.html.md#self-hosted-mineid) * [Mixcloud OAuth2](backends/mixcloud.html.md) * [Backend class](backends/mixcloud.html.md#backend-class) * [NationBuilder](backends/nationbuilder.html.md) * [Backend class](backends/nationbuilder.html.md#backend-class) * [Naver](backends/naver.html.md) * [Backend class](backends/naver.html.md#backend-class) * [NFDI (OpenID Connect)](backends/nfdi.html.md) * [Backend classes](backends/nfdi.html.md#backend-classes) * [Username](backends/nfdi.html.md#username) * [Scopes](backends/nfdi.html.md#scopes) * [NGP VAN ActionID](backends/ngpvan_actionid.html.md) * [Backend class](backends/ngpvan_actionid.html.md#backend-class) * [Odnoklassniki.ru](backends/odnoklassnikiru.html.md) * [Backend classes](backends/odnoklassnikiru.html.md#backend-classes) * [OAuth2](backends/odnoklassnikiru.html.md#oauth2) * [IFrame applications](backends/odnoklassnikiru.html.md#iframe-applications) * [Okta](backends/okta.html.md) * [Backend classes](backends/okta.html.md#backend-classes) * [Okta OAuth2](backends/okta.html.md#okta-oauth2) * [Okta OpenID Connect](backends/okta.html.md#okta-openid-connect) * [Scopes and external groups](backends/okta.html.md#scopes-and-external-groups) * [User identification](backends/okta.html.md#user-identification) * [OpenStreetMap OAuth 2](backends/openstreetmap_oauth2.html.md) * [Backend class](backends/openstreetmap_oauth2.html.md#backend-class) * [Configuration](backends/openstreetmap_oauth2.html.md#configuration) * [Extra Configuration](backends/openstreetmap_oauth2.html.md#extra-configuration) * [OIDC (OpenID Connect)](backends/oidc.html.md) * [Backend class](backends/oidc.html.md#backend-class) * [Nonce lifetime](backends/oidc.html.md#nonce-lifetime) * [IdP Setup](backends/oidc.html.md#idp-setup) * [Authentication Request Parameters](backends/oidc.html.md#authentication-request-parameters) * [Username](backends/oidc.html.md#username) * [First Name](backends/oidc.html.md#first-name) * [Last Name](backends/oidc.html.md#last-name) * [Full Name](backends/oidc.html.md#full-name) * [Email](backends/oidc.html.md#email) * [Scopes](backends/oidc.html.md#scopes) * [External memberships](backends/oidc.html.md#external-memberships) * [Orbi](backends/orbi.html.md) * [Backend class](backends/orbi.html.md#backend-class) * [ORCID](backends/orcid.html.md) * [Backend classes](backends/orcid.html.md#backend-classes) * [Member API](backends/orcid.html.md#member-api) * [Sandbox](backends/orcid.html.md#sandbox) * [Osso - Open Source SAML SSO](backends/osso.html.md) * [Backend class](backends/osso.html.md#backend-class) * [Patreon](backends/patreon.html.md) * [Backend class](backends/patreon.html.md#backend-class) * [Pinterest](backends/pinterest.html.md) * [Backend class](backends/pinterest.html.md#backend-class) * [PixelPin](backends/pixelpin.html.md) * [Backend class](backends/pixelpin.html.md#backend-class) * [PixelPin OpenID Connect](backends/pixelpin.html.md#pixelpin-openid-connect) * [Podio](backends/podio.html.md) * [Backend class](backends/podio.html.md#backend-class) * [Qiita](backends/qiita.html.md) * [Backend class](backends/qiita.html.md#backend-class) * [QQ](backends/qq.html.md) * [Backend class](backends/qq.html.md#backend-class) * [Quizlet](backends/quizlet.html.md) * [Backend class](backends/quizlet.html.md#backend-class) * [Reddit](backends/reddit.html.md) * [Backend class](backends/reddit.html.md#backend-class) * [Salesforce](backends/salesforce.html.md) * [Backend classes](backends/salesforce.html.md#backend-classes) * [Seznam](backends/seznam.html.md) * [Backend class](backends/seznam.html.md#backend-class) * [User ID](backends/seznam.html.md#user-id) * [Shopify](backends/shopify.html.md) * [Backend class](backends/shopify.html.md#backend-class) * [SimpleLogin](backends/simplelogin.html.md) * [Backend class](backends/simplelogin.html.md#backend-class) * [Sketchfab](backends/sketchfab.html.md) * [Backend class](backends/sketchfab.html.md#backend-class) * [Slack](backends/slack.html.md) * [Backend class](backends/slack.html.md#backend-class) * [SoundCloud](backends/soundcloud.html.md) * [Backend class](backends/soundcloud.html.md#backend-class) * [Spotify](backends/spotify.html.md) * [Backend class](backends/spotify.html.md#backend-class) * [OAuth2](backends/spotify.html.md#oauth2) * [SUSE](backends/suse.html.md) * [Backend class](backends/suse.html.md#backend-class) * [openSUSE OpenID](backends/suse.html.md#opensuse-openid) * [Stackoverflow](backends/stackoverflow.html.md) * [Backend class](backends/stackoverflow.html.md#backend-class) * [Steam OpenID](backends/steam.html.md) * [Backend class](backends/steam.html.md#backend-class) * [StockTwits](backends/stocktwits.html.md) * [Backend class](backends/stocktwits.html.md#backend-class) * [Strava](backends/strava.html.md) * [Backend class](backends/strava.html.md#backend-class) * [Stripe](backends/stripe.html.md) * [Backend class](backends/stripe.html.md#backend-class) * [Taobao OAuth](backends/taobao.html.md) * [Backend class](backends/taobao.html.md#backend-class) * [Telegram](backends/telegram.html.md) * [Backend class](backends/telegram.html.md#backend-class) * [Trello](backends/trello.html.md) * [Backend class](backends/trello.html.md#backend-class) * [TripIt](backends/tripit.html.md) * [Backend class](backends/tripit.html.md#backend-class) * [Tumblr](backends/tumblr.html.md) * [Backend class](backends/tumblr.html.md#backend-class) * [Twilio Connect](backends/twilio.html.md) * [Backend class](backends/twilio.html.md#backend-class) * [Configuration](backends/twilio.html.md#configuration) * [Initiating the connection](backends/twilio.html.md#initiating-the-connection) * [Security limitations](backends/twilio.html.md#security-limitations) * [Twitch](backends/twitch.html.md) * [Backend classes](backends/twitch.html.md#backend-classes) * [X (formerly Twitter)](backends/twitter.html.md) * [Backend class](backends/twitter.html.md#backend-class) * [X OAuth 2](backends/twitter_oauth2.html.md) * [Backend class](backends/twitter_oauth2.html.md#backend-class) * [Udata](backends/udata.html.md) * [Backend class](backends/udata.html.md#backend-class) * [Datagouvfr OAuth2](backends/udata.html.md#datagouvfr-oauth2) * [Uber](backends/uber.html.md) * [Backend class](backends/uber.html.md#backend-class) * [OAuth2](backends/uber.html.md#oauth2) * [Untappd](backends/untappd.html.md) * [Backend class](backends/untappd.html.md#backend-class) * [Upwork](backends/upwork.html.md) * [Backend class](backends/upwork.html.md#backend-class) * [OAuth1](backends/upwork.html.md#oauth1) * [Hashicorp Vault](backends/vault.html.md) * [Backend class](backends/vault.html.md#backend-class) * [Vault OIDC configuration](backends/vault.html.md#vault-oidc-configuration) * [Scopes](backends/vault.html.md#scopes) * [Lightspeed Retail (X-Series)](backends/vend.html.md) * [Backend class](backends/vend.html.md#backend-class) * [Vimeo](backends/vimeo.html.md) * [Backend classes](backends/vimeo.html.md#backend-classes) * [VK.com (former Vkontakte)](backends/vk.html.md) * [Backend classes](backends/vk.html.md#backend-classes) * [VK ID](backends/vk.html.md#vk-id) * [Legacy OAuth2](backends/vk.html.md#legacy-oauth2) * [Legacy application OAuth2](backends/vk.html.md#legacy-application-oauth2) * [Legacy OpenAPI](backends/vk.html.md#legacy-openapi) * [Weibo OAuth](backends/weibo.html.md) * [Backend class](backends/weibo.html.md#backend-class) * [XING](backends/xing.html.md) * [Backend class](backends/xing.html.md#backend-class) * [Yahoo](backends/yahoo.html.md) * [Backend class](backends/yahoo.html.md#backend-class) * [Microsoft Viva Engage](backends/yammer.html.md) * [Backend classes](backends/yammer.html.md#backend-classes) * [Production Mode](backends/yammer.html.md#production-mode) * [Staging Mode](backends/yammer.html.md#staging-mode) * [Zotero](backends/zotero.html.md) * [Backend class](backends/zotero.html.md#backend-class) ## Display metadata Every shipped backend has a human-readable `title`. Some also provide an `icon` filename referencing social-core’s packaged SVG artwork. Applications choose how to render missing icons. Custom backend classes can declare these attributes: ```default class CompanyAuth(OpenIdConnectAuth): name = "company" title = "Company account" icon = None ``` The display title is independent of the stable `name` identifier. Changing branding does not require renaming stored associations or configuration keys. Titles are plain strings; applications localize generic labels such as e-mail or password. See [Django Framework](configuration/django.html.md) for Django template metadata and staticfiles integration. # backends/instagram.html.md # Instagram ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `instagram` | `social_core.backends.instagram.InstagramOAuth2` | Instagram uses OAuth v2 for Authentication. - Register a new application at the [Instagram API](http://instagr.am/developer/), and - Add instagram backend to `AUTHENTICATION_SETTINGS`: ```default AUTHENTICATION_SETTINGS = ( ... 'social_core.backends.instagram.InstagramOAuth2', ... ) ``` - fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_INSTAGRAM_KEY = '' SOCIAL_AUTH_INSTAGRAM_SECRET = '' ``` - extra scopes can be defined by using: ```default SOCIAL_AUTH_INSTAGRAM_AUTH_EXTRA_ARGUMENTS = {'scope': 'likes comments relationships'} ``` # backends/justgiving.html.md # Just Giving ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `justgiving` | `social_core.backends.justgiving.JustGivingOAuth2` | ## OAuth2 Follow the steps at [Just Giving API Docs](https://api.justgiving.com/docs) to register your application and get the needed keys. - Add the Just Giving OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.justgiving.JustGivingOAuth2', ... ) ``` - Fill `App Key` and `App Secret` values in the settings: ```default SOCIAL_AUTH_JUSTGIVING_KEY = '' SOCIAL_AUTH_JUSTGIVING_SECRET = '' ``` # backends/kakao.html.md # Kakao ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `kakao` | `social_core.backends.kakao.KakaoOAuth2` | Kakao uses OAuth v2 for Authentication. - Register a new applicationat the [Kakao API](https://developers.kakao.com/docs/restapi), and - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_KAKAO_KEY = '' SOCIAL_AUTH_KAKAO_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_KAKAO_SCOPE = [...] ``` # backends/keycloak.html.md # Keycloak - Open Source Red Hat SSO ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `keycloak` | `social_core.backends.keycloak.KeycloakOAuth2` | Keycloak is an open source IAM and SSO system. ## IdP Setup To configure Keycloak: 1. Log into your Keycloak Admin Console and select your Realm 2. Navigate to **Clients** > **Create** 3. Configure the client: * **Client ID**: Choose a meaningful name (e.g., `django-app`) * **Client Protocol**: `openid-connect` * **Access Type**: `confidential` * **Valid Redirect URIs**: `https://your-domain.com/complete/keycloak/` 4. Save and go to the **Credentials** tab to get the **Client Secret** 5. Under **Fine Grain OpenID Connect Configuration** (found in the client’s Settings or Advanced Settings tab; location may vary depending on Keycloak version), set: * **User Info Signed Response Algorithm**: `RS256` * **Request Object Signature Algorithm**: `RS256` 6. Get the active public key from **Realm Settings** > **Keys** > **RS256** 7. Create an **Audience Mapper** for the client to ensure its **Client ID** is included in the access token’s `aud` claim. In recent Keycloak versions, navigate to **Client scopes** > `-dedicated` > **Add mapper** > **Audience**, select the client under **Included Client Audience**, and enable **Add to access token**. 8. Note the **Authorization URL** and **Token URL** from the Realm OpenID Endpoint Configuration ## Application Configuration Add Keycloak to your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.keycloak.KeycloakOAuth2', 'django.contrib.auth.backends.ModelBackend', ) ``` Configure with values from your Keycloak client: ```default SOCIAL_AUTH_KEYCLOAK_KEY = 'test-django-oidc' SOCIAL_AUTH_KEYCLOAK_SECRET = 'a7a41-245e-...' SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = \ 'MIIBIjANBxxxdSD' SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = \ 'https://iam.example.com/auth/realms/voxcloud-staff/protocol/openid-connect/auth' SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = \ 'https://iam.example.com/auth/realms/voxcloud-staff/protocol/openid-connect/token' ``` ## Audience validation `SOCIAL_AUTH_KEYCLOAK_KEY` is the OAuth **Client ID**. The backend also uses this value as the expected audience when validating the access token. Therefore, the exact value configured in `SOCIAL_AUTH_KEYCLOAK_KEY` must be present in the token’s `aud` claim. The `azp` (authorized party) claim does not satisfy audience validation. For example, with `SOCIAL_AUTH_KEYCLOAK_KEY = 'test-django-oidc'`, the access token should contain claims similar to: ```default { "azp": "test-django-oidc", "aud": ["test-django-oidc"] } ``` If the Client ID is missing from `aud`, configure the Audience Mapper described above. Otherwise, authentication fails with an audience validation error even when `azp` identifies the correct client. ## Signing key rotation The Keycloak backend verifies access tokens with the single static key configured in `SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY`. It does not use the JWT header’s `kid` (key ID) to select a key and does not fetch keys from Keycloak’s JWKS endpoint. The configured key must therefore be the active RS256 signing key from the same realm that issues the token. After a realm signing-key rotation, update `SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY`; otherwise, authentication fails with a signature verification error. The token’s `kid` can be compared with the key ID shown under **Realm Settings** > **Keys** to diagnose a mismatch. For automatic signing-key discovery and rotation, consider using the generic [OIDC (OpenID Connect)](backends/oidc.html.md) backend instead. It uses OpenID Connect discovery, selects keys from the provider’s JWKS by `kid`, and refreshes the JWKS when a new key appears. ## User ID Configuration The default behavior is to associate users via the `sub` (subject) field from the JWT token. However, you can configure which field to use as the unique user identifier by setting: ```default SOCIAL_AUTH_KEYCLOAK_ID_KEY = 'email' ``` This can be useful if you want to use email, username, or another field as the unique identifier instead of the `sub` field. Associations created by older social-core releases used the normalized `preferred_username` value and migrate to `sub` on the next successful authentication. #### WARNING Usernames and email addresses can change or be reassigned. Selecting one as `ID_KEY` can allow a different provider account to match a stale local association. See the [Configurable User ID Key](../configuration/settings.html#configurable-user-id-key) documentation for more information about this feature. ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/kick.html.md # Kick ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `kick` | `social_core.backends.kick.KickOAuth2` | Kick works similar to Facebook (OAuth) but with Oauth2.1. - Register a new application in the [developer tab](https://kick.com/settings/developer) of your Kick settings page, set the callback URL to `http://example.com/complete/kick/` replacing `example.com` with your domain. - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_KICK_KEY = '' SOCIAL_AUTH_KICK_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_KICK_SCOPE = [...] ``` Further documentation at [Developer Guide](https://docs.kick.com/getting-started/generating-tokens-oauth2-flow). # backends/lastfm.html.md # Last.fm ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `lastfm` | `social_core.backends.lastfm.LastFmAuth` | Last.fm uses a similar authentication process than OAuth2 but it’s not. In order to enable the support for it just: - Register an application at [Get an API Account](http://www.last.fm/api/account/create), set the Last.fm callback to something sensible like [http://your.site/complete/lastfm](http://your.site/complete/lastfm) - Fill in the **API Key** and **API Secret** values in your settings: ```default SOCIAL_AUTH_LASTFM_KEY = '' SOCIAL_AUTH_LASTFM_SECRET = '' ``` - Enable the backend in `AUTHENTICATION_BACKENDS` setting. Last.fm does not expose a stable account identifier in its authentication session response. The backend is therefore association-only: an authenticated local user must initiate and complete the connection. Last.fm cannot create a local user or authenticate a logged-out user. # backends/launchpad.html.md # Launchpad ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `launchpad` | `social_core.backends.launchpad.LaunchpadOpenId` | [Ubuntu Launchpad](https://launchpad.net/) OpenID doesn’t require major settings beside being defined on `AUTHENTICATION_BACKENDS``: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.launchpad.LaunchpadOpenId', ... ) ``` # backends/lifescience.html.md # Lifescience AAI ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------------------------| | `life_science` | `social_core.backends.lifescience.LifeScienceOpenIdConnect` | Lifescience’s OpenID Connect (OIDC) backend requires the following minimum configuration: ```default SOCIAL_AUTH_LIFESCIENCE_OIDC_KEY = '' SOCIAL_AUTH_LIFESCIENCE_OIDC_SECRET = '' ``` ## Scopes The default scopes will include the user’s email. You can request additional claims, for example: ```default SOCIAL_AUTH_LIFESCIENCE_OIDC_SCOPE = ['eduperson_entitlement'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_LIFESCIENCE_OIDC_IGNORE_DEFAULT_SCOPE = True ``` # backends/lifescience_eosc.html.md # Lifescience AAI - (Temporary instance for EOSC node) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |---------------------|----------------------------------------------------------------------| | `life_science_eosc` | `social_core.backends.lifescience_eosc.LifeScienceEoscOpenIdConnect` | Lifescience’s OpenID Connect (OIDC) backend requires the following minimum configuration: ```default SOCIAL_AUTH_LIFESCIENCE_EOSC_OIDC_KEY = '' SOCIAL_AUTH_LIFESCIENCE_EOSC_OIDC_SECRET = '' ``` ## Scopes The default scopes will include the user’s email. You can request additional claims, for example: ```default SOCIAL_AUTH_LIFESCIENCE_EOSC_OIDC_SCOPE = ['eduperson_entitlement'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_LIFESCIENCE_EOSC_OIDC_IGNORE_DEFAULT_SCOPE = True ``` # backends/line.html.md # Line.me ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `line` | `social_core.backends.line.LineOAuth2` | Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_LINE_KEY = '...' SOCIAL_AUTH_LINE_SECRET = '...' ``` # backends/linkedin.html.md # LinkedIn ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |--------------------------|-------------------------------------------------------| | `linkedin-openidconnect` | `social_core.backends.linkedin.LinkedinOpenIdConnect` | | `linkedin-oauth2` | `social_core.backends.linkedin.LinkedinOAuth2` | | `linkedin-mobile-oauth2` | `social_core.backends.linkedin.LinkedinMobileOAuth2` | Sign In with LinkedIn only support OpenID Connect since August 1, 2023. The previous OAuth2 has been deprecated. See [LinkedIn OpenID Connect](https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2) for more details. LinkedIn previously supported OAuth2. Migration between each type is fairly simple since the same Key / Secret pair is used for both authentication types. LinkedIn OAuth2 setup is similar to any other OAuth2 service. The auth flow is explained on [LinkedIn Developers](https://docs.microsoft.com/en-us/linkedin/shared/authentication/authentication) docs. First you will need to register an app att [LinkedIn Developer Network](https://www.linkedin.com/secure/developer). ## OpenID Connect - Fill the application key and secret in your settings: ```default SOCIAL_AUTH_LINKEDIN_OPENIDCONNECT_KEY = '' SOCIAL_AUTH_LINKEDIN_OPENIDCONNECT_SECRET = '' ``` ## OAuth2 - Fill the application key and secret in your settings: ```default SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY = '' SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET = '' ``` - Application scopes can be specified by: ```default SOCIAL_AUTH_LINKEDIN_OAUTH2_SCOPE = [...] ``` Check the available options at [LinkedIn Scopes](https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin) (also called as permissions by LinkedIn). If you want to request a user’s email address, you’ll need specify that your application needs access to the email address use the `r_emailaddress` scope. - To request extra fields using [LinkedIn fields selectors](https://docs.microsoft.com/en-us/linkedin/shared/references/v2/profile/lite-profile) just define this setting: ```default SOCIAL_AUTH_LINKEDIN_OAUTH2_FIELD_SELECTORS = [...] ``` with the needed fields selectors, also define `SOCIAL_AUTH_LINKEDIN_OAUTH2_EXTRA_DATA` properly, that way the values will be stored in `UserSocialAuth.extra_data` field. By default `id`, `firstName` and `lastName` are requested and stored. For example, to request a user’s email from the Linkedin API and store the information in `UserSocialAuth.extra_data`, you would add these settings: ```default # Add email to requested authorizations. SOCIAL_AUTH_LINKEDIN_OAUTH2_SCOPE = ['r_liteprofile', 'r_emailaddress'] # Add the fields so they will be requested from linkedin. SOCIAL_AUTH_LINKEDIN_OAUTH2_FIELD_SELECTORS = ['emailAddress'] # Arrange to add the fields to UserSocialAuth.extra_data SOCIAL_AUTH_LINKEDIN_OAUTH2_EXTRA_DATA = [('id', 'id'), ('firstName', 'first_name'), ('lastName', 'last_name'), ('emailAddress', 'email_address')] ``` Looks like LinkedIn is forcing the definition of the callback URL in the application when OAuth2 is used. Follow the setup 1 carefully as per [Linkedin App Setup](https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow) to add a redirect url/callback url. Be sure to set the proper values, otherwise a `(400) Client Error: Bad Request` might be returned by their service. # backends/live.html.md # MSN Live Connect ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `live` | `social_core.backends.live.LiveOAuth2` | Live uses OAuth2 for its connect workflow, notice that it isn’t OAuth WRAP. - Register a new application at [Live Connect Developer Center](https://account.live.com/developers/applications/create), set your site domain as redirect domain, - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_LIVE_KEY = '' SOCIAL_AUTH_LIVE_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_LIVE_SCOPE = [...] ``` Defaults are `wl.basic` and `wl.emails`. Latter one is necessary to retrieve user email. - Ensure to have a valid `Redirect URL` (`http://your-domain/complete/live`) defined in the application if `Enhanced security redirection` is enabled. # backends/livejournal.html.md # LiveJournal ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------------| | `livejournal` | `social_core.backends.livejournal.LiveJournalOpenId` | LiveJournal provides OpenID, it doesn’t require any major settings in order to work, beside being defined on `AUTHENTICATION_BACKENDS``: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.livejournal.LiveJournalOpenId', ... ) ``` LiveJournal OpenID is provided by URLs in the form `http://.livejournal.com`, this application retrieves the `username` from the data in the current request by checking a parameter named `openid_lj_user` which can be sent by `POST` or `GET`. # backends/loginradius.html.md # LoginRadius ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `loginradius` | `social_core.backends.loginradius.LoginRadiusAuth` | LoginRadius uses OAuth2 for Authentication with other providers with an HTML widget used to trigger the auth process. - Register a new application at the [LoginRadius Website](https://loginradius.com/), and - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_LOGINRADIUS_KEY = '' SOCIAL_AUTH_LOGINRADIUS_SECRET = '' ``` - Since the auth process is triggered by LoginRadius JS script, you need to sever such content to the user, all you need to do that is a template with the following content: ```default
``` Put that content in a template named `loginradius.html` (accessible to your framework), or define a name with `SOCIAL_AUTH_LOGINRADIUS_TEMPLATE` setting, like: ```default SOCIAL_AUTH_LOGINRADIUS_LOCAL_HTML = 'loginradius.html' ``` The template context will have the current backend instance under the `backend` name, also the application key (`LOGINRADIUS_KEY`) and the redirect URL (`LOGINRADIUS_REDIRECT_URL`). - Further documentation can be found at [LoginRadius API Documentation](http://api.loginradius.com/help/) and [LoginRadius Datapoints](http://www.loginradius.com/datapoints/) # backends/lyft.html.md # Lyft ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `lyft` | `social_core.backends.lyft.LyftOAuth2` | Lyft implements OAuth2 as its authorization service. To setup a Lyft backend: 1. Register a new application via the [Lyft Developer Portal](https://developer.lyft.com/). 2. Add the Lyft OAuth2 backend as an option in your settings: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.lyft.LyftOAuth2', ... ) ``` 3. Use the `Client Id` and `Client Secret` from the Developer Portal into your settings: ```default SOCIAL_AUTH_LYFT_KEY = '' SOCIAL_AUTH_LYFT_SECRET = '' ``` 4. Specify the scope that your app should have access to: ```default SOCIAL_AUTH_LYFT_SCOPE = ['public', 'profile', 'rides.read', 'rides.request'] ``` To learn more about the API and the calls that are available, read the [Lyft API Documentation](https://developer.lyft.com/docs). # backends/mailchimp.html.md # MailChimp ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `mailchimp` | `social_core.backends.mailchimp.MailChimpOAuth2` | MailChimp uses OAuth v2 for Authentication, check the [official docs](https://apidocs.mailchimp.com/oauth2/). - Create an app by filling out the form here: [Add App](https://admin.mailchimp.com/account/oauth2/) - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_MAILCHIMP_KEY = '' SOCIAL_AUTH_MAILCHIMP_SECRET = '' ``` - Add the backend to the `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.mailchimp.MailChimpOAuth2', ... ) ``` - Then you can start using `{% url social_core:begin 'mailchimp' %}` in your templates # backends/mailru.html.md # Mail.ru OAuth ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |-----------------|--------------------------------------------| | `mailru-oauth2` | `social_core.backends.mailru.MailruOAuth2` | | `mailru` | `social_core.backends.mailru.MRGOAuth2` | Mail.ru uses OAuth2 workflow. [Register new application](https://oauth.mail.ru/app/) to use it and fill in settings: ```default SOCIAL_AUTH_MAILRU_KEY = '' SOCIAL_AUTH_MAILRU_SECRET = '' ``` Add `social_core.backends.mailru.MRGOAuth2` to `AUTHENTICATION_BACKENDS` to activate Mail.ru authorization. The `mailru` backend identifies users by the stable `id` returned by the userinfo endpoint. Associations created by older social-core releases used the email address and migrate on the next successful authentication. The legacy `mailru-oauth2` backend already uses its stable `uid` field. ## Legacy OAuth2 authorization Also available `social_core.backends.mailru.MailruOAuth2` for authorization with `connect.mail.ru` server. [Create an app](https://api.mail.ru/sites/my/add) and set following settings: ```default SOCIAL_AUTH_MAILRU_OAUTH2_KEY = '' SOCIAL_AUTH_MAILRU_OAUTH2_SECRET = '' ``` # backends/mapmyfitness.html.md # MapMyFitness ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------------| | `mapmyfitness` | `social_core.backends.mapmyfitness.MapMyFitnessOAuth2` | MapMyFitness uses OAuth v2 for authentication. - Register a new application at the [MapMyFitness API](https://www.mapmyapi.com), and - fill `key` and `secret` values in the settings: ```default SOCIAL_AUTH_MAPMYFITNESS_KEY = '' SOCIAL_AUTH_MAPMYFITNESS_SECRET = '' ``` # backends/mediawiki.html.md # MediaWiki OAuth1 backend ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `mediawiki` | `social_core.backends.mediawiki.MediaWiki` | ## Usage In addition to the general setup you need to define the following settings: ```default SOCIAL_AUTH_MEDIAWIKI_KEY = SOCIAL_AUTH_MEDIAWIKI_SECRET = SOCIAL_AUTH_MEDIAWIKI_URL = 'https://meta.wikimedia.org/w/index.php' ``` In the OAuth consumer registration you can choose the option to: > Allow consumer to specify a callback in requests > and use “callback” URL above as a required prefix This is preferable. If your URL is https://myurl.org/ use the following option: ```default SOCIAL_AUTH_MEDIAWIKI_CALLBACK = \ 'https://myurl.org/oauth/complete/mediawiki' ``` But it is also possible to use: ```default SOCIAL_AUTH_MEDIAWIKI_CALLBACK = 'oob' ``` ## General documentation [https://www.mediawiki.org/wiki/Extension:OAuth](https://www.mediawiki.org/wiki/Extension:OAuth) ## Developer documentation [https://www.mediawiki.org/wiki/OAuth/For_Developers](https://www.mediawiki.org/wiki/OAuth/For_Developers) ## Code based on [https://github.com/mediawiki-utilities/python-mwoauth](https://github.com/mediawiki-utilities/python-mwoauth) ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/meetup.html.md # Meetup ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `meetup` | `social_core.backends.meetup.MeetupOAuth2` | Meetup.com uses OAuth2 for its auth mechanism. - Register a new OAuth Consumer at [Meetup Consumer Registration](https://secure.meetup.com/meetup_api/oauth_consumers/create), set your consumer name, redirect uri. - Fill `key` and `secret` values in the settings: ```default SOCIAL_AUTH_MEETUP_KEY = '' SOCIAL_AUTH_MEETUP_SECRET = '' ``` # backends/mendeley.html.md # Mendeley ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-------------------|------------------------------------------------| | `mendeley-oauth2` | `social_core.backends.mendeley.MendeleyOAuth2` | Mendeley supports OAuth2. In order to support OAuth2: - Register a new application at [Mendeley Application Registration](http://dev.mendeley.com/applications/register/). - Fill **Application ID** and **Application Secret** values: ```default SOCIAL_AUTH_MENDELEY_OAUTH2_KEY = '' SOCIAL_AUTH_MENDELEY_OAUTH2_SECRET = '' ``` # backends/microsoftgraph.html.md # Microsoft Graph ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-------------------|--------------------------------------------------| | `microsoft-graph` | `social_core.backends.microsoft.MicrosoftOAuth2` | 1. Go to [Azure portal](https://portal.azure.com/) and create an application. 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_MICROSOFT_GRAPH_KEY = '...' SOCIAL_AUTH_MICROSOFT_GRAPH_SECRET = '...' ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.microsoft.MicrosoftOAuth2', ... ) ``` [Register an application with the Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app). # backends/mineid.html.md # MineID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `mineid` | `social_core.backends.mineid.MineIDOAuth2` | MineID works similar to Facebook (OAuth). - Register a new application at [MineID.org](https://www.mineid.org/), set the callback URL to `http://example.com/complete/mineid/` replacing `example.com` with your domain. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_MINEID_KEY = '' SOCIAL_AUTH_MINEID_SECRET = '' ``` ## Self-hosted MineID Since MineID is an Open Source software and can be self-hosted, you can change settings to point to your instance: ```default SOCIAL_AUTH_MINEID_HOST = 'www.your-mineid-instance.com' SOCIAL_AUTH_MINEID_SCHEME = 'https' # or 'http' ``` # backends/mixcloud.html.md # Mixcloud OAuth2 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------| | `mixcloud` | `social_core.backends.mixcloud.MixcloudOAuth2` | The [Mixcloud API](http://www.mixcloud.com/developers/documentation) offers support for authorization. To enable this backend: - Register a new application at [Mixcloud Developers](http://www.mixcloud.com/developers) - Add Mixcloud backend to `AUTHENTICATION_BACKENDS` in settings: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.mixcloud.MixcloudOAuth2', ) ``` - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_MIXCLOUD_KEY = '' SOCIAL_AUTH_MIXCLOUD_SECRET = '' ``` - Similar to the other OAuth backends you can define: ```default SOCIAL_AUTH_MIXCLOUD_EXTRA_DATA = [('username', 'username'), ('name', 'name'), ('pictures', 'pictures'), ('url', 'url')] ``` as a list of tuples `(response name, alias)` to store user profile data on the `UserSocialAuth.extra_data`. Mixcloud does not expose a documented stable account identifier. The backend is association-only: an authenticated local user must initiate and complete the connection. Mixcloud cannot create a local user or authenticate a logged-out user. # backends/nationbuilder.html.md # NationBuilder ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-----------------|----------------------------------------------------------| | `nationbuilder` | `social_core.backends.nationbuilder.NationBuilderOAuth2` | [NationBuilder supports OAuth2](http://nationbuilder.com/api_quickstart) as their authentication mechanism. Follow these steps in order to use it: - Register a new application at your [Nation Admin panel](https://psa.nationbuilder.com/admin/apps) (define the Callback URL to `http://example.com/complete/nationbuilder/` where `example.com` is your domain). - Fill the `Client ID` and `Client Secret` values from the newly created application: ```default SOCIAL_AUTH_NATIONBUILDER_KEY = '' SOCIAL_AUTH_NATIONBUILDER_SECRET = '' ``` - Also define your NationBuilder slug: ```default SOCIAL_AUTH_NATIONBUILDER_SLUG = 'your-nationbuilder-slug' ``` - Enable the backend in `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.nationbuilder.NationBuilderOAuth2' ... ) ``` # backends/naver.html.md # Naver ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `naver` | `social_core.backends.naver.NaverOAuth2` | Naver uses OAuth v2 for Authentication. - Register a new application at the [Naver API](https://nid.naver.com/devcenter/docs.nhn?menu=API), and - add naver oauth backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.naver.NaverOAuth2', ... ) ``` - fill `Client ID` and `Client Secret` from developer.naver.com values in the settings: ```default SOCIAL_AUTH_NAVER_KEY = '' SOCIAL_AUTH_NAVER_SECRET = '' ``` - you can get EXTRA_DATA: ```default SOCIAL_AUTH_NAVER_EXTRA_DATA = ['nickname', 'gender', 'age', 'birthday', 'profile_image'] ``` # backends/nfdi.html.md # NFDI (OpenID Connect) ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------------|------------------------------------------------------------| | `helmholtz` | `social_core.backends.nfdi.NFDIOpenIdConnect` | | `xcs` | `social_core.backends.nfdi.XcsOpenIdConnect` | | `textplus` | `social_core.backends.nfdi.TextplusOpenIdConnect` | | `mardi` | `social_core.backends.nfdi.MardiOpenIdConnect` | | `objects` | `social_core.backends.nfdi.ObjectsOpenIdConnect` | | `culture` | `social_core.backends.nfdi.CultureOpenIdConnect` | | `cat` | `social_core.backends.nfdi.CatOpenIdConnect` | | `chem` | `social_core.backends.nfdi.ChemOpenIdConnect` | | `datascience` | `social_core.backends.nfdi.DatascienceOpenIdConnect` | | `energy` | `social_core.backends.nfdi.EnergyOpenIdConnect` | | `ing` | `social_core.backends.nfdi.IngOpenIdConnect` | | `matWerk` | `social_core.backends.nfdi.MatWerkOpenIdConnect` | | `daphne` | `social_core.backends.nfdi.DaphneOpenIdConnect` | | `fairmat` | `social_core.backends.nfdi.FairmatOpenIdConnect` | | `immuno` | `social_core.backends.nfdi.ImmunoOpenIdConnect` | | `punch` | `social_core.backends.nfdi.PunchOpenIdConnect` | | `helmholtz` | `social_core.backends.nfdi.HelmholtzOpenIdConnect` | | `infraproxy-staging` | `social_core.backends.nfdi.InfraproxyStagingOpenIdConnect` | | `infraproxy` | `social_core.backends.nfdi.InfraproxyOpenIdConnect` | | `eduid` | `social_core.backends.nfdi.EduidOpenIdConnect` | | `eduid-staging` | `social_core.backends.nfdi.EduidStagingOpenIdConnect` | The [NFDI](https://nfdi.de) backend allows authentication against all OIDC providers of NFDI (German National Research Data Infrastructure) and also for the Helmholtz AAI. These backends provides their endpoints, as well as the default scopes. The provided backends are: `` XcsOpenIdConnect TextplusOpenIdConnect MardiOpenIdConnect ObjectsOpenIdConnect CultureOpenIdConnect CatOpenIdConnect ChemOpenIdConnect DatascienceOpenIdConnect EnergyOpenIdConnect IngOpenIdConnect MatWerkOpenIdConnect DaphneOpenIdConnect FairmatOpenIdConnect ImmunoOpenIdConnect PunchOpenIdConnect HelmholtzOpenIdConnect InfraproxyStagingOpenIdConnect InfraproxyOpenIdConnect EduidOpenIdConnect EduidStagingOpenIdConnect `` A minimum configuration is: ```default SOCIAL_AUTH_OIDC_KEY = '' SOCIAL_AUTH_OIDC_SECRET = '' ``` The remaining configuration will be auto-detected, by fetching: ```default /.well-known/openid-configuration ``` This class can be used standalone, but may also be used as the base class for some other backends. Find more information at the [NFDI_AAI_WEBSITE](https://doc.nfdi-aai.de) ## Username The [NFDI](https://nfdi.de) backend will check for a `preferred_username` key in the values returned by the server. If the username is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_USERNAME_KEY = 'nickname' ``` This setting indicates that the username should be populated by the `nickname` claim instead. ## Scopes The default set of scopes requested are those configured by default in the cleass. You can request additional claims, for example: ```default SOCIAL_AUTH_OIDC_SCOPE = ['groups'] ``` # backends/ngpvan_actionid.html.md # NGP VAN ActionID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-------------------|----------------------------------------------| | `actionid-openid` | `social_core.backends.ngpvan.ActionIDOpenID` | [NGP VAN](http://www.ngpvan.com/)’s [ActionID](http://developers.ngpvan.com/action-id) service provides an OpenID 1.1 endpoint, which provides first name, last name, email address, and phone number. ActionID doesn’t require major settings beside being defined on `AUTHENTICATION_BACKENDS` ```python SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.ngpvan.ActionIDOpenID', ... ) ``` If you want to be able to access the “phone” attribute offered by NGP VAN within `extra_data` you can add the following to your settings: ```python SOCIAL_AUTH_ACTIONID_OPENID_AX_EXTRA_DATA = [ ('http://openid.net/schema/contact/phone/business', 'phone') ] ``` NGP VAN offers the ability to have your domain whitelisted, which will disable the “{domain} is requesting a link to your ActionID” warning when your app attempts to login using an ActionID account. Contact [NGP VAN Developer Support](http://developers.ngpvan.com/support/contact) for more information # backends/oauth.html.md # OAuth [OAuth](http://oauth.net/) communication demands a set of keys exchange to validate the client authenticity prior to user approbation. Twitter, and Facebook facilitates these keys by application registration, Google works the same, but provides the option for unregistered applications. Check next sections for details. [OAuth](http://oauth.net/) backends also can store extra data in `UserSocialAuth.extra_data` field by defining a set of values names to retrieve from service response. Settings is per backend and its name is dynamically checked using uppercase backend name as prefix: ```default SOCIAL_AUTH__EXTRA_DATA ``` Example: ```default SOCIAL_AUTH_FACEBOOK_EXTRA_DATA = [(..., ...)] ``` Settings must be a list of tuples mapping value name in response and value alias used to store. A third value (boolean) is supported, its purpose is to signal if the value should be discarded if it evaluates to `False`, this is to avoid replacing old (needed) values when they don’t form part of current response. If not present, then this check is avoided and the value will replace any data. ## Token renewal Use the stored social account to renew credentials explicitly: ```default social.refresh_token(strategy=strategy) ``` To renew only when the stored access token has expired, use: ```default access_token = social.get_access_token(strategy) ``` Tokens with five seconds or less remaining are considered expired. The backend selects the renewal credential through `get_refresh_token()`. Standard OAuth2 backends require a nonempty stored `refresh_token`; they never send an access token in its place. Facebook OAuth2 and Facebook App instead exchange the stored access token using `fb_exchange_token`. When no renewal credential is available, `refresh_token()` raises `AuthCredentialError` with `code='reauthentication_required'`, `source='storage'`, `stage='refresh'`, and `recovery='reauthenticate'` if the stored access token is known to have expired. `get_access_token()` propagates this error. Applications should catch this credential error and arrange another provider login. See [Exceptions](exceptions.html.md). If expiry is unknown or the access token is still valid, an explicit refresh without a renewal credential returns without a request or changes to stored credentials. `get_access_token()` returns the stored access token in those cases; unknown expiry does not guarantee the token remains valid. A missing backend or a backend without a refresh method remains a no-op. Invalid expiry data raises the existing `AuthResponseError` with `code='invalid_expiry'`. Refresh tokens are optional. Depending on the provider, requesting one may require additional scopes such as `offline_access` or explicit consent. Configure these requirements for the provider rather than assuming every login issues a refresh token. Backends must store issued refresh tokens in `EXTRA_DATA`. To retain an existing token when a refresh response omits a replacement, use: ```default EXTRA_DATA = [('refresh_token', 'refresh_token', True)] ``` Zoom and PayPal, including PayPal Sandbox, store refresh tokens by default and save replacements returned during renewal. Existing associations that lack a refresh token require another provider login to obtain and store one. ### Migration Earlier versions fell back to the access token when no refresh token was stored. Applications refreshing expired accounts must now handle `reauthentication_required`. Custom backends that deliberately exchange access tokens must override `get_refresh_token()` as described in [Adding a new backend](backends/implementation.html.md). # backends/odnoklassnikiru.html.md # Odnoklassniki.ru ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |------------------------|----------------------------------------------------------| | `odnoklassniki-oauth2` | `social_core.backends.odnoklassniki.OdnoklassnikiOAuth2` | | `odnoklassniki-app` | `social_core.backends.odnoklassniki.OdnoklassnikiApp` | There are two options with Odnoklassniki: either you use OAuth2 workflow to authenticate odnoklassniki users at external site, or you authenticate users within your IFrame application. ## OAuth2 If you use OAuth2 workflow, you need to: - register a new application with [OAuth registration form](https://apiok.ru/wiki/pages/viewpage.action?pageId=42476652) - fill out some settings: ```default SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_KEY = '' SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_SECRET = '' SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_PUBLIC_NAME = '' ``` - add `'social_core.backends.odnoklassniki.OdnoklassnikiOAuth2'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. ## IFrame applications If you want to authenticate users in your IFrame application, - read [Rules for application developers](https://apiok.ru/wiki/display/ok/Odnoklassniki.ru+Third+Party+Platform) - fill out [Developers registration form](https://apiok.ru/wiki/pages/viewpage.action?pageId=5668937) - get your personal sandbox - fill out some settings: ```default SOCIAL_AUTH_ODNOKLASSNIKI_APP_KEY = '' SOCIAL_AUTH_ODNOKLASSNIKI_APP_SECRET = '' SOCIAL_AUTH_ODNOKLASSNIKI_APP_PUBLIC_NAME = '' ``` - add `'social_core.backends.odnoklassniki.OdnoklassnikiApp'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS` - sign a public offer and do some bureaucracy You may also use: ```default SOCIAL_AUTH_ODNOKLASSNIKI_APP_EXTRA_USER_DATA_LIST ``` Defaults to empty tuple, for the list of available fields see [Documentation on user.getInfo](https://apiok.ru/wiki/display/ok/REST+API+-+users.getInfo) # backends/oidc.html.md # OIDC (OpenID Connect) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------------| | `oidc` | `social_core.backends.open_id_connect.OpenIdConnectAuth` | The [OIDC](https://openid.net/connect/) backend allows authentication against a generic OIDC provider. The backend class is OpenIdConnectAuth with name oidc. A minimum configuration is: ```default SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = 'https://.....' SOCIAL_AUTH_OIDC_KEY = '' SOCIAL_AUTH_OIDC_SECRET = '' ``` The remaining configuration will be auto-detected, by fetching: ```default /.well-known/openid-configuration ``` This class can be used standalone, but is also the base class for some other backends. ## Nonce lifetime Each login attempt stores a one-use nonce with its creation time and lifetime. The nonce expires after 30 minutes by default. Configure a different positive integer duration in seconds with: ```default SOCIAL_AUTH_OIDC_NONCE_LIFETIME = 1800 ``` For other backends inheriting from this class, replace `OIDC` with the backend’s settings prefix. This duration bounds the time from starting authentication to validating the ID token; it is independent of `ID_TOKEN_MAX_AGE`, which limits the age of the ID token itself. An expired nonce rejects the login, so the user must start again. Successful validation consumes the nonce. Refresh requests and resumed partial pipelines do not reuse it. LinkedIn OpenID Connect does not create or send nonces because its backend does not validate them. Custom subclasses can set the class attribute `USE_NONCE` to `False` when their protocol-specific validation does not use server-created nonces; this is not a deployment setting. Failed and abandoned attempts can leave nonce records behind. Django deployments should regularly run `manage.py clearsocial`; see [Django Framework](configuration/django.html.md) for cleanup and upgrade guidance. ## IdP Setup To configure your OIDC Identity Provider for use with this backend: 1. Create a new application/client in your IdP with type “Web Application” 2. Set the **Redirect URI** (also called Callback URL) to: ```default https://your-domain.com/complete/oidc/ ``` Replace `your-domain.com` with your actual application domain. 3. Configure scopes to include at minimum: `openid`, `profile`, `email` 4. Note the generated **Client ID** and **Client Secret** for use in your Django settings 5. Ensure your IdP exposes the OpenID Connect discovery endpoint at: `https://your-idp-domain/.well-known/openid-configuration` #### NOTE For development, you can use `http://localhost:8000/complete/oidc/` as the redirect URI. ## Authentication Request Parameters All this parameters are optional and they might not be supported by the OIDC provider. ### Prompt This informs the OIDC provider whether the OIDC provider prompts the user for reauthentication and consent. ```default SOCIAL_AUTH_OIDC_PROMPT = ' ...' ``` Defined values are - `none` - `login` - `consent` - `select_account` ## Username The [OIDC](https://openid.net/connect/) backend will check for a `preferred_username` key in the values returned by the server. If the username is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_USERNAME_KEY = 'nickname' ``` This setting indicates that the username should be populated by the `nickname` claim instead. ## First Name The [OIDC](https://openid.net/connect/) backend will check for a `given_name` key in the values returned by the server. If the first name is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_FIRST_NAME_KEY = 'first_name' ``` This setting indicates that the first name should be populated by the `first_name` claim instead. ## Last Name The [OIDC](https://openid.net/connect/) backend will check for a `family_name` key in the values returned by the server. If the last name is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_LAST_NAME_KEY = 'last_name' ``` This setting indicates that the last name should be populated by the `last_name` claim instead. ## Full Name The [OIDC](https://openid.net/connect/) backend will check for a `name` key in the values returned by the server. If the full name is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_FULLNAME_KEY = 'full_name' ``` This setting indicates that the full name should be populated by the `full_name` claim instead. ## Email The [OIDC](https://openid.net/connect/) backend will check for a `email` key in the values returned by the server. If the email is under a different key, this can be overridden: ```default SOCIAL_AUTH_OIDC_EMAIL_KEY = 'mail' ``` This setting indicates that the email should be populated by the `mail` claim instead. ## Scopes The default set of scopes requested are “openid”, “profile” and “email”. You can request additional claims, for example: ```default SOCIAL_AUTH_OIDC_SCOPE = ['groups'] ``` and you can prevent the inclusion of the default scopes using: ```default SOCIAL_AUTH_OIDC_IGNORE_DEFAULT_SCOPE = True ``` ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/okta.html.md # Okta ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------------|-------------------------------------------------------------| | `okta-oauth2` | `social_core.backends.okta.OktaOAuth2` | | `okta-openidconnect` | `social_core.backends.okta_openidconnect.OktaOpenIdConnect` | This section describes how to setup the different services provided by Okta. ## Okta OAuth2 ### IdP Setup To configure Okta for OAuth2: 1. Log into your Okta Admin Console 2. Navigate to **Applications** > **Create App Integration** 3. Select **OIDC - OpenID Connect** and **Web Application** 4. Set the **Sign-in redirect URI** to: ```default https://your-domain.com/complete/okta-oauth2/ ``` 5. Save and note the **Client ID**, **Client Secret**, and **Okta domain** (e.g., `https://dev-123456.okta.com`) #### IMPORTANT Do NOT use the `/oauth2/default` endpoint for Okta authentication. ### Application Configuration Fill `Client ID`, `Client Secret` and `API URL (e.g. https://dev-123456.okta.com/oauth2)` settings with the values from the IdP setup above: ```default SOCIAL_AUTH_OKTA_OAUTH2_KEY = '' SOCIAL_AUTH_OKTA_OAUTH2_SECRET = '' SOCIAL_AUTH_OKTA_OAUTH2_API_URL = '' ``` ## Okta OpenID Connect ### IdP Setup Follow the same steps as OAuth2 above, but use the redirect URI: ```default https://your-domain.com/complete/okta-openidconnect/ ``` ### Application Configuration Fill `Client ID`, `Client Secret` and `API URL (e.g. https://dev-123456.okta.com/oauth2)` settings with the values from the IdP setup: ```default SOCIAL_AUTH_OKTA_OPENIDCONNECT_KEY = '' SOCIAL_AUTH_OKTA_OPENIDCONNECT_SECRET = '' SOCIAL_AUTH_OKTA_OPENIDCONNECT_API_URL = '' ``` ## Scopes and external groups Both backends request `openid`, `profile`, and `email` by default. For the org authorization server (`/oauth2/v1/authorize`), request the `groups` scope with the setting matching your backend: ```default # social_core.backends.okta.OktaOAuth2 SOCIAL_AUTH_OKTA_OAUTH2_SCOPE = ['groups'] # social_core.backends.okta_openidconnect.OktaOpenIdConnect SOCIAL_AUTH_OKTA_OPENIDCONNECT_SCOPE = ['groups'] ``` These settings add to the default scopes. `SOCIAL_AUTH_OIDC_SCOPE` applies only to the generic OpenID Connect backend. For a custom authorization server (`/oauth2/{authorizationServerId}/v1/authorize`, including `default`), `groups` is not an automatically defined scope. Configure the groups claim for any scope or for specific scopes, then request any scope associated with that claim using the matching `SCOPE` setting. If the claim is available with the default scopes, no additional scope is needed; Okta’s custom-server example requests only `openid`. Request `groups` only if you have defined that scope on the custom server and associated it with the claim; requesting an undefined scope causes `invalid_scope`. Configure Okta to issue a groups claim with an appropriate group filter; requesting a scope alone does not configure the claim. See [Okta’s groups claim guide](https://developer.okta.com/docs/guides/customize-tokens-groups-claim/main/) for org and custom authorization server configuration. Group extraction and local synchronization are opt-in. For `OktaOAuth2`, configure the literal claim name and map external groups to existing Django group names: ```default SOCIAL_AUTH_OKTA_OAUTH2_GROUPS_KEY = 'groups' SOCIAL_AUTH_OKTA_OAUTH2_GROUPS_MAP = { 'engineering': ['Engineering'], } from social_core.pipeline import DEFAULT_AUTH_PIPELINE SOCIAL_AUTH_PIPELINE = ( *DEFAULT_AUTH_PIPELINE, 'social_core.pipeline.user.sync_groups', ) ``` For `OktaOpenIdConnect`, use the corresponding settings with the same pipeline: ```default SOCIAL_AUTH_OKTA_OPENIDCONNECT_GROUPS_KEY = 'groups' SOCIAL_AUTH_OKTA_OPENIDCONNECT_GROUPS_MAP = { 'engineering': ['Engineering'], } ``` `OktaOAuth2` reads the claim from UserInfo. `OktaOpenIdConnect` prefers the validated ID token and falls back to UserInfo only when its subject matches the ID token. Enabling extraction does not automatically request additional scopes. Synchronization adds desired mapped memberships and removes obsolete mapped memberships, preserving unrelated Django groups. It does not create groups. An empty claim clears managed memberships; a missing configured claim fails authentication by default. If Okta omits the claim for users with no groups, explicitly set `SOCIAL_AUTH_OKTA_OAUTH2_GROUPS_MISSING_AS_EMPTY = True` or `SOCIAL_AUTH_OKTA_OPENIDCONNECT_GROUPS_MISSING_AS_EMPTY = True` for your backend. Malformed claims still fail authentication. See [External groups](groups.html.md) for validation, authentication restrictions, and synchronization behavior. ## User identification Both Okta backends identify users by the stable `sub` claim. Associations created by older social-core releases used `preferred_username` and migrate to `sub` on the next successful authentication. See [Configurable User ID Key](../configuration/settings.html#configurable-user-id-key) for migration controls and custom identifier settings. # backends/openid.html.md # OpenID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `openid` | `social_core.backends.open_id.OpenIdAuth` | [OpenID](http://openid.net/) support is simpler to implement than [OAuth](http://oauth.net/). Google and Yahoo providers are supported by default, others are supported by POST method providing endpoint URL. The generic OpenID backend stores the identity URL asserted by the provider as the user’s unique identifier. Because this identifier is protocol-derived rather than selected from a response mapping, the generic `ID_KEY` setting does not apply. [OpenID](http://openid.net/) backends can store extra data in `UserSocialAuth.extra_data` field by defining a set of values names to retrieve from any of the used schemas, AttributeExchange and SimpleRegistration. As their keywords differ we need two settings. Settings is per backend, so we have two possible values for each one. Name is dynamically checked using uppercase backend name as prefix: ```default SOCIAL_AUTH__SREG_EXTRA_DATA SOCIAL_AUTH__AX_EXTRA_DATA ``` Example: ```default SOCIAL_AUTH_GOOGLE_SREG_EXTRA_DATA = [(..., ...)] SOCIAL_AUTH_GOOGLE_AX_EXTRA_DATA = [(..., ...)] ``` Settings must be a list of tuples mapping value name in response and value alias used to store. A third value (boolean) is supported to, it’s purpose is to signal if the value should be discarded if it evaluates to `False`, this is to avoid replacing old (needed) values when they don’t form part of current response. If not present, then this check is avoided and the value will replace any data. ## Username The [OpenID](http://openid.net/) backend will check for a `username` key in the values returned by the server, but default to `first-name` + `last-name` if that key is missing. It’s possible to indicate the username key in the values If the username is under a different key with a setting, but backends should have defined a default value. For example: ```default SOCIAL_AUTH_FEDORA_USERNAME_KEY = 'nickname' ``` This setting indicates that the username should be populated by the `nickname` value in the Fedora [OpenID](http://openid.net/) provider. # backends/openstreetmap_oauth2.html.md # OpenStreetMap OAuth 2 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |------------------------|-----------------------------------------------------------------| | `openstreetmap-oauth2` | `social_core.backends.openstreetmap_oauth2.OpenStreetMapOAuth2` | OpenStreetMap supports the OAuth 2.0 protocol. It supports two types of OAuth 2.0 flows: 1. Authorization code with [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) 2. Authorization code ## Configuration - Login to your account - Register your application as OAuth 2 application on the [My Client Applications page](https://www.openstreetmap.org/oauth2/applications) * Set the redirect URIs to [https://example.com/complete/openstreetmap-oauth2/](https://example.com/complete/openstreetmap-oauth2/) * PKCE can be enabled/disabled using the “Confidential application?” flag. * Select all required Permissions. * Scopes names are shown next to each permission after saving. - Fill *Client ID* in `SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_KEY` and *Client Secret* in `SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SECRET` > SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_KEY = ‘…’ > SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SECRET = ‘…’ Note: *Client Secret* isn’t required for PKCE. - Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.openstreetmap_oauth2.OpenStreetMapOAuth2', ... ) ``` Access tokens currently do not expire automatically. More documentation at [OpenStreetMap Wiki](http://wiki.openstreetmap.org/wiki/OAuth): ## Extra Configuration - You can specify the scopes that your application requires: ```default SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SCOPE = [ 'read_prefs' ] ``` - You can choose to disable PKCE: ```default SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_USE_PKCE = False ``` By default, True is set. # backends/orbi.html.md # Orbi ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `orbi` | `social_core.backends.orbi.OrbiOAuth2` | Orbi OAuth v2 for Authentication. - Register a new applicationat the [Orbi API](http://orbi.kr), and - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_ORBI_KEY = '' SOCIAL_AUTH_ORBI_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_KAKAO_SCOPE = ['all'] ``` # backends/orcid.html.md # ORCID ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |-----------------|-------------------------------------------------| | `orcid` | `social_core.backends.orcid.ORCIDOAuth2` | | `orcid-sandbox` | `social_core.backends.orcid.ORCIDOAuth2Sandbox` | [ORCID](https://orcid.org/) uses OAuth 2 for authentication. - Register an ORCID account, go to [Developer tools](https://orcid.org/developer-tools), enable the public API, create a new application, set the redirect URI to `http://example.com/complete/orcid/` replacing `example.com` with your domain. - Fill the `Client ID` and `Client secret` values from the app details in Developer tools (you might need to press “Show details”) in the settings: ```default SOCIAL_AUTH_ORCID_KEY = '' SOCIAL_AUTH_ORCID_SECRET = '' ``` ## Member API You can subscribe to gain access to an [API with extended capabilities](https://orcid.org/organizations/integrators/API). Use `'social_core.backends.orcid.ORCIDMemberOAuth2'` class in your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. ## Sandbox ORCID supports a sandbox mode for testing, there’s a custom backend for it which name is `orcid-sandbox` instead of `orcid`. Same settings apply but use these instead: ```default SOCIAL_AUTH_ORCID_SANDBOX_KEY = '' SOCIAL_AUTH_ORCID_SANDBOX_SECRET = '' ``` Sandbox is also available for Member API. You will have to register for with ORCID it [separately](https://orcid.org/content/register-client-application-sandbox). # backends/osso.html.md # Osso - Open Source SAML SSO ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `osso` | `social_core.backends.osso.OssoOAuth2` | Osso is an open source service that handles SAML tenant onboarding, documentation and authentication. Your application can then consume normalized user profile resources as part of an OAuth 2.0 authorization code grant flow. Learn more about Osso at [https://ossoapp.com](https://ossoapp.com) or continue below to start consuming your Osso instance from your application via Python Social Auth. To enable Osso as a backend: - On your project settings, add Osso on your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.osso.OssoOAuth2', ) ``` - Create or update an OAuth Client in your Osso instance, adding a redirect URI to your allow `http://example.com/complete/osso/` replacing `http://example.com` with your application’s domain. Grab the `Client ID` and `Client Secret` to use in your application. - Add these values of `Client ID` and `Client Secret` from Osso in your project settings file. The `Client ID` should be added on `SOCIAL_AUTH_OSSO_KEY` and the `Client Secret` should be added on `SOCIAL_AUTH_OSSO_SECRET`. You also need to add your Osso instance base URL as `SOCIAL_AUTH_OSSO_BASE_URL`: ```default SOCIAL_AUTH_OSSO_KEY = os.getenv('SOCIAL_AUTH_OSSO_KEY') SOCIAL_AUTH_OSSO_SECRET = os.getenv('SOCIAL_AUTH_OSSO_SECRET') SOCIAL_AUTH_OSSO_BASE_URL = 'https://demo.ossoapp.com' ``` When constructing your sign in flow, Osso supports passing an `email` or `domain` parameter in order to route the user to the correct IDP. If you don’t include one of these parameters, and instead implement a button, Osso will display a hosted login page. Here’s an example login form with `email`: ```html+django ``` # backends/patreon.html.md # Patreon ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `patreon` | `social_core.backends.patreon.PatreonOAuth2` | Patreon supports OAuth 2.0 1. Register a new application at [Patreon Developer Portal](https://www.patreon.com/portal/registration/register-clients). 2. Use the `social.backends.patreon.PatreonOAuth2`, either by adding it to your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS` or instantiating it directly. 3. Fill in the the `Client ID` and `Client Secret`: ```default SOCIAL_AUTH_PATREON_KEY = '' SOCIAL_AUTH_PATREON_SECRET = '' ``` 4. Checkout the [Patreon API Docs](https://docs.patreon.com/) for more information. # backends/pinterest.html.md # Pinterest ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `pinterest` | `social_core.backends.pinterest.PinterestOAuth2` | Pinterest implemented OAuth2 protocol for their authentication mechanism. To enable `python-social-auth` support follow this steps: 1. Go to [Pinterest developers zone](https://developers.pinterest.com/apps/) and create an application. 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_PINTEREST_KEY = '...' SOCIAL_AUTH_PINTEREST_SECRET = '...' SOCIAL_AUTH_PINTEREST_SCOPE = [ 'read_public', 'write_public', 'read_relationships', 'write_relationships' ] ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.pinterest.PinterestOAuth2', ... ) ``` # backends/pixelpin.html.md # PixelPin ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |--------------------------|-------------------------------------------------------| | `pixelpin-openidconnect` | `social_core.backends.pixelpin.PixelPinOpenIDConnect` | PixelPin supports OpenID Connect. ## PixelPin OpenID Connect Developer documentation for PixelPin can be found at [http://developer.pixelpin.co.uk/](http://developer.pixelpin.co.uk/). To setup OpenID Connect do the following: - Register a new developer account at [PixelPin Developers](http://developer.pixelpin.co.uk/). You require a PixelPin account to create developer accounts. Sign up at [PixelPin Account Page](https://login.pixelpin.co.uk/) For the value of redirect uri, use whatever path you need to return to on your web application. The example code provided with the plugin uses `http:///complete/pixelpin-oauth2/`. Once verified by email, record the values of client id and secret for the next step. - Fill **Consumer Key** and **Consumer Secret** values in your settings.py file: ```default SOCIAL_AUTH_PIXELPIN_OAUTH2_KEY = '' SOCIAL_AUTH_PIXELPIN_OAUTH2_SECRET = '' ``` - Add `'social_core.backends.pixelpin.PixelPinOpenIDConnect'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. # backends/podio.html.md # Podio ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `podio` | `social_core.backends.podio.PodioOAuth2` | Podio offers OAuth2 as their auth mechanism. In order to enable it, follow: - Register a new application at [Podio API Keys](https://developers.podio.com/api-key) - Fill **Client Id** and **Client Secret** values: ```default SOCIAL_AUTH_PODIO_KEY = '' SOCIAL_AUTH_PODIO_SECRET = '' ``` # backends/qiita.html.md # Qiita ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `qiita` | `social_core.backends.qiita.QiitaOAuth2` | Qiita - Register a new application at [Qiita](https://qiita.com/settings/applications), set the callback URL to `http://example.com/complete/qiita/` replacing `example.com` with your domain. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_QIITA_KEY = '' SOCIAL_AUTH_QIITA_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_QIITA_SCOPE = [...] ``` See auth scopes at [Qiita Scopes docs](https://qiita.com/api/v2/docs#スコープ). - Users are identified by the stable `permanent_id`. Associations created by older social-core releases used the renameable `id` and migrate on the next successful authentication. The following legacy setting remains accepted, but no longer changes the default: ```default SOCIAL_AUTH_QIITA_IDENTIFIED_BY_PERMANENT_ID = True ``` # backends/qq.html.md # QQ ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------| | `qq` | `social_core.backends.qq.QQOAuth2` | QQ implemented OAuth2 protocol for their authentication mechanism. To enable `python-social-auth` support follow this steps: 1. Go to [QQ](http://connect.qq.com/) and create an application. 2. Fill App Id and Secret in your project settings: ```default SOCIAL_AUTH_QQ_KEY = '...' SOCIAL_AUTH_QQ_SECRET = '...' ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.qq.QQOAuth2', ... ) ``` The values for `nickname`, `figureurl_qq_1` and `gender` will be stored in the `extra_data` field. The `nickname` will be used as the account username. `figureurl_qq_1` can be used as the profile image. Sometimes nickname will duplicate with another `qq` account, to avoid this issue it’s possible to use `openid` as `username` by define this setting: ```default SOCIAL_AUTH_QQ_USE_OPENID_AS_USERNAME = True ``` # backends/quizlet.html.md # Quizlet ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `quizlet` | `social_core.backends.quizlet.QuizletOAuth2` | Quizlet uses OAuth v2 for Authentication. - Register a new application at the [Quizlet API](https://quizlet.com/api-dashboard), and - Add the Quizlet backend to `AUTHENTICATION_SETTINGS`: ```default AUTHENTICATION_SETTINGS = ( ... 'social_core.backends.quizlet.QuizletOAuth2', ... ) ``` - fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_QUIZLET_KEY = '' SOCIAL_AUTH_QUIZLET_SECRET = '' SOCIAL_AUTH_QUIZLET_SCOPE = ['read', 'write_set'] # 'write_group' is also available ``` # backends/reddit.html.md # Reddit ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `reddit` | `social_core.backends.reddit.RedditOAuth2` | Reddit implements [OAuth2 authentication workflow](https://github.com/reddit/reddit/wiki/OAuth2). To enable it, just follow: - Register an application at [Reddit Preferences Apps](https://ssl.reddit.com/prefs/apps/) - Fill the **Consumer Key** and **Consumer Secret** values in your settings: ```default SOCIAL_AUTH_REDDIT_KEY = '' SOCIAL_AUTH_REDDIT_SECRET = '' ``` - By default the token is not permanent, it will last an hour. To get a refresh token just define: ```default SOCIAL_AUTH_REDDIT_AUTH_EXTRA_ARGUMENTS = {'duration': 'permanent'} ``` This will store the `refresh_token` in `UserSocialAuth.extra_data` attribute, to refresh the access token just do: ```default from social_django.utils import load_strategy strategy = load_strategy(backend='reddit') user = User.objects.get(pk=foo) social = user.social_auth.filter(provider='reddit')[0] social.refresh_token(strategy=strategy, redirect_uri='http://localhost:8000/complete/reddit/') ``` Reddit requires `redirect_uri` when refreshing the token and it must be the same value used during the auth process. # backends/salesforce.html.md # Salesforce ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |-----------------------------|-----------------------------------------------------------| | `salesforce-oauth2` | `social_core.backends.salesforce.SalesforceOAuth2` | | `salesforce-oauth2-sandbox` | `social_core.backends.salesforce.SalesforceOAuth2Sandbox` | Salesforce uses OAuth v2 for Authentication, check the [official docs](https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_web_server_oauth_flow.htm). - Create an app following the steps in the [Defining Connected Apps](https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_defining_remote_access_applications.htm) docs. - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_SALESFORCE_OAUTH2_KEY = '' SOCIAL_AUTH_SALESFORCE_OAUTH2_SECRET = '' ``` - Add the backend to the `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.salesforce.SalesforceOAuth2', ... ) ``` - Then you can start authentication from your templates with a POST form: ```default
{% csrf_token %}
``` If using the sandbox mode: - Fill these settings instead: ```default SOCIAL_AUTH_SALESFORCE_OAUTH2_SANDBOX_KEY = '' SOCIAL_AUTH_SALESFORCE_OAUTH2_SANDBOX_SECRET = '' ``` - And this backend: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.salesforce.SalesforceOAuth2Sandbox', ... ) ``` - Then you can start authentication from your templates with a POST form: ```default
{% csrf_token %}
``` # backends/saml.html.md # SAML ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------| | `saml` | `social_core.backends.saml.SAMLAuth` | The SAML backend allows users to authenticate with any provider that supports the SAML 2.0 protocol (commonly used for corporate or academic single sign on). The SAML backend for python-social-auth allows your web app to act as a SAML Service Provider. You can configure one or more SAML Identity Providers that users can use for authentication. For example, if your users are students, you could enable Harvard and MIT as identity providers, so that students of either of those two universities can use their campus login to access your app. ## Required Dependency You need to install [python3-saml](https://github.com/onelogin/python3-saml), this is included in the `saml` extra when installing `social-core`. In case you run into `lxml & xmlsec libxml2 library version mismatch` error, it is caused by `lxml` being built against a different version of `libxml2` than `xmlsec`. To avoid this, please install both packages from the source and build them against system libraries: ```sh # Install system dependencies sudo apt install libxmlsec1-dev # Install Python packages from the source pip install --no-binary lxml --no-binary xmlsec -e 'social-core[saml]' ``` ## Required Configuration At a minimum, you must add the following to your project’s settings: - `SOCIAL_AUTH_SAML_SP_ENTITY_ID`: The SAML Entity ID for your app. This should be a URL that includes a domain name you own. It doesn’t matter what the URL points to. Example: `http://saml.yoursite.com` - `SOCIAL_AUTH_SAML_SP_PUBLIC_CERT`: The X.509 certificate string for the key pair that your app will use. You can generate a new self-signed key pair with: ```default openssl req -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.key ``` The contents of `saml.crt` should then be used as the value of this setting (you can omit the first and last lines, which aren’t required). - `SOCIAL_AUTH_SAML_SP_PRIVATE_KEY`: The private key to be used by your app. If you used the example openssl command given above, set this to the contents of `saml.key` (again, you can omit the first and last lines). - `SOCIAL_AUTH_SAML_ORG_INFO`: A dictionary that contains information about your app. You must specify values for English at a minimum. Each language’s entry should specify a `name` (not shown to the user), a `displayname` (shown to the user), and a URL. See the following example: ```default { "en-US": { "name": "example", "displayname": "Example Inc.", "url": "http://example.com", } } ``` - `SOCIAL_AUTH_SAML_TECHNICAL_CONTACT`: A dictionary with two values, `givenName` and `emailAddress`, describing the name and email of a technical contact responsible for your app. Example: ```default { "givenName": "Tech Gal", "emailAddress": "technical@example.com" } ``` - `SOCIAL_AUTH_SAML_SUPPORT_CONTACT`: A dictionary with two values, `givenName` and `emailAddress`, describing the name and email of a support contact for your app. Example: ```default { "givenName": "Support Guy", "emailAddress": "support@example.com", } ``` - `SOCIAL_AUTH_SAML_ENABLED_IDPS`: The most important setting. List the Entity ID, SSO URL, and x.509 public key certificate for each provider that your app wants to support. The SSO URL must support the `HTTP-Redirect` binding. You can get these values from the provider’s XML metadata. Here’s an example, for [TestShib](https://www.testshib.org/) (the values come from TestShib’s [metadata](https://www.testshib.org/metadata/testshib-providers.xml)): ```default { "testshib": { "entity_id": "https://idp.testshib.org/idp/shibboleth", "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO", "x509cert": "MIIEDjCCAvagAwIBAgIBADA ... 8Bbnl+ev0peYzxFyF5sQA==", } } ``` Each IDP can define configuration keys to avoid having to use uniform resource name’s (ie: `urn:oid:0.9.2342.19200300.100.1.3` for email address) as attributes to map user details required to complete account creation. The values associated with the attr_\* keys correspond to the keys specified as attributes in the IDP. #### IMPORTANT **Version 4.8.0+ Behavior Change:** When you explicitly configure an attribute (e.g., `attr_first_name`), that attribute **must** be present in the SAML response from the IdP. If it is missing, authentication will fail with an error like: `Missing needed parameter first_name (configured by attr_first_name)`. **Options:** 1. **Remove the configuration** if the attribute is not provided by your IdP. The backend will automatically try to map using built-in attribute names. 2. **Ensure your IdP provides the attribute** with the exact name you configured. 3. **Use the correct attribute name** from your IdP’s SAML response (check the actual attribute names sent by your IdP). Extending on the “testshib” example: ```default { "testshib": { "entity_id": "https://idp.testshib.org/idp/shibboleth", "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO", "x509cert": "MIIEDjCCAvagAwIBAgIBADA ... 8Bbnl+ev0peYzxFyF5sQA==", "attr_user_permanent_id": "email", "attr_first_name": "first_name", "attr_last_name": "last_name", "attr_username": "email", "attr_email": "email", } } ``` In this example, the attr_user_permanent_id and attr_email are both set to the email address passed back in the attribute key ‘email’. The SAML backend prefixes this permanent identifier with the IdP name. Use `attr_user_permanent_id` to choose the identifier attribute; the generic `ID_KEY` setting does not apply to SAML identities. Note: testshib does not provide email as an attribute. This was tested using Okta and G Suite (formerly Google Apps for Business). **Built-in Attribute Mappings:** If you omit the `attr_*` configuration keys, the backend will automatically try to extract user details using a list of commonly used attribute names, including both namespaced URN variants (like `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname`) and simple names (like `first_name`, `firstName`, `given_name`). Missing attributes will be silently ignored when using the built-in mappings. ## Basic Usage - Set all of the required configuration variables described above. - Generate the SAML XML metadata for your app. The best way to do this is to create a new view/page/URL in your app that will call the backend’s `generate_metadata_xml()` method. Here’s an example of how to do this in Django: ```default def saml_metadata_view(request): complete_url = reverse('social:complete', args=("saml", )) saml_backend = load_backend( load_strategy(request), "saml", redirect_uri=complete_url, ) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type='text/xml') ``` - Download the metadata for your app that was generated by the above method, and send it to each Identity Provider (IdP) that you wish to use. Each IdP must install and configure your metadata on their system before it will work. - Now everything is set! To allow users to login with any given IdP, you need to submit the python-social-auth “begin”/”auth” URL and include an `idp` parameter that specifies the name of the IdP to use. This is needed since the backend supports multiple IdPs. The names of the IdPs are the keys used in the `SOCIAL_AUTH_SAML_ENABLED_IDPS` setting. Django example: ```default
{% csrf_token %}
``` - Testing with the [TestShib](https://www.testshib.org/) provider is recommended, as it is known to work well. ## Advanced Settings - `SOCIAL_AUTH_SAML_SP_EXTRA`: This can be set to a dict, and any key/value pairs specified here will be passed to the underlying `python-saml` library configuration’s `sp` setting. Refer to the `python-saml` documentation for details. To publish a rollover certificate in advance of changing, use `SOCIAL_AUTH_SAML_SP_EXTRA` to set `['sp']['x509certNew']` of `python-saml`: ```default { "x509certNew": "MIIEDjCCAvagAwIBAgIBADA ... 8Bbnl+ev0peYzxFyF5sQA==", } ``` - `SOCIAL_AUTH_SAML_SECURITY_CONFIG`: This can be set to a dict, and any key/value pairs specified here will be passed to the underlying `python-saml` library configuration’s `security` setting. Two useful keys that you can set are `metadataCacheDuration` and `metadataValidUntil`, which control the expiry time of your XML metadata. By default, a cache duration of 10 days will be used, which means that IdPs are allowed to cache your metadata for up to 10 days, but no longer. `metadataCacheDuration` must be specified as an ISO 8601 duration string (e.g. P1D for one day). - `SOCIAL_AUTH_SAML_EXTRA_DATA`: This can be set to a list of tuples similar to the OAuth backend setting. It maps IDP attributes to extra_data attributes. Each attribute will be a list of values (even if only 1 value) per how [python3-saml](https://github.com/onelogin/python3-saml) processes attributes: ```default SOCIAL_AUTH_SAML_EXTRA_DATA = [('attribute_name', 'extra_data_name_for_attribute'), ('department', 'department'), ('manager_full_name', 'manager_full_name')] ``` - In `SOCIAL_AUTH_SAML_ENABLED_IDPS`: `x509certMulti["signing"]` is a list that can be used instead of `x509cert`. For example, when the IdP certificate is rotated, use: ```default SOCIAL_AUTH_SAML_ENABLED_IDPS = { "my_idp": { "entity_id": "https://...", "url": "https://...", "x509certMulti": { "signing": [ # Old certificate """ -----BEGIN CERTIFICATE----- MIIEDjCCAvagAwIBAgIBADA ... -----END CERTIFICATE----- """, # New certificate """ -----BEGIN CERTIFICATE----- 8Bbnl+ev0peYzxFyF5sQA ... -----END CERTIFICATE----- """ ] } } } ``` ## Advanced Usage You can subclass the `SAMLAuth` backend to provide custom functionality. In particular, there are two methods that are designed for subclasses to override: - `get_idp(self, idp_name)`: Given the name of an IdP, return an instance of `SAMLIdentityProvider` with the details of the IdP. Override this method if you wish to use some other method for configuring the available identity providers, such as fetching them at runtime from another server, or using a list of providers from a Shibboleth federation. - `_check_entitlements(self, idp, attributes)`: This method gets called during the login process and is where you can decide to accept or reject a user based on the user’s SAML attributes. For example, you can restrict access to your application to only accept users who belong to a certain department. After inspecting the passed attributes parameter, do nothing to allow the user to login, or raise `social_core.exceptions.AuthPolicyError` to reject the user. ## Troubleshooting **Error: “SAML login failed: missing AuthnRequest ID”** For Service Provider initiated login, the SAML response must match the authentication request stored in the user’s session. SAML Identity Providers usually return the response with a cross-site POST request. Django’s default `SESSION_COOKIE_SAMESITE = "Lax"` setting prevents the session cookie from being sent with that request. `social-auth-app-django` preserves the server-side session identifier in SAML `RelayState` and restores the session before validating the response. Use a current `social-auth-app-django` release and a server-side Django session engine. In multi-instance deployments, every instance that can handle the login or callback must use the same session storage. Database and cached database engines meet this requirement when configured with shared services. The cache engine must use a shared backend, and the file engine is suitable only for a single instance or a shared filesystem. The signed-cookie session backend cannot restore session changes through this mechanism. Also verify that the login was initiated by the same browser, that the Identity Provider returns `RelayState` unchanged, and that only one SAML login is active for the Identity Provider in that browser session. As a workaround, `SESSION_COOKIE_SAMESITE` can be set to `"None"` so the cookie is sent with the cross-site POST. This requires secure HTTPS cookies and reduces the protection provided by the SameSite policy, so prefer server-side session restoration. **Error: “Missing needed parameter first_name (configured by attr_first_name)”** This error occurs when you have explicitly configured an attribute mapping (like `attr_first_name`) but your IdP is not providing that attribute in the SAML response. **Solution:** 1. **Check what attributes your IdP actually provides.** Inspect the SAML response from your IdP to see the exact attribute names being sent. 2. **Remove unused attribute configurations.** If your IdP doesn’t provide `first_name`, simply remove `"attr_first_name": "first_name"` from your configuration. The backend will try to use built-in mappings instead. 3. **Use the correct attribute name.** If your IdP provides the attribute with a different name (e.g., `givenName` or a namespaced URN like `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname`), use that name in your configuration: ```default "attr_first_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", ``` 4. **Configure your IdP** to include the attribute in the SAML response if you need it. **Example:** For Google G Suite SSO, if you’re not receiving `first_name` and `last_name` attributes, remove those configurations and let the backend use its built-in mappings: ```default SOCIAL_AUTH_SAML_ENABLED_IDPS = { "gsuite": { "entity_id": "...", "url": "...", "x509cert": "...", "attr_user_permanent_id": "email", "attr_username": "email", "attr_email": "email", # Remove attr_first_name and attr_last_name if not provided by IdP } } ``` ## External memberships See [External groups](groups.html.md) for opt-in extraction, group-based login restrictions, and local group synchronization. No separate extraction pipeline step is needed. # backends/seznam.html.md # Seznam ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-----------------|--------------------------------------------| | `seznam-oauth2` | `social_core.backends.seznam.SeznamOAuth2` | Seznam supports OAuth2 for developers to authenticate users for their apps. The documentation for the API can be found at [Seznam OAuth documentation](https://vyvojari.seznam.cz/oauth/doc?lang=en). This backend also provides additional configuration options to support slightly different enterprise versions. 1. Register a new application at [Application management](https://vyvojari.seznam.cz/oauth/admin), set the `redirect_uri` to `http://example.com/complete/seznam-oauth2/`, replacing `example.com` with your domain. 2. Fill `client_id` and `client_secret` values in the settings: ```default SOCIAL_AUTH_SEZNAM_OAUTH2_KEY = '' SOCIAL_AUTH_SEZNAM_OAUTH2_SECRET = '' ``` - If you would like to access some additional information from the user, you can set the `SOCIAL_AUTH_SEZNAM_OAUTH2_SCOPE` setting to a list of extra scopes that are supported according to the [scope documentation](https://vyvojari.seznam.cz/oauth/scopes?lang=en). For example, to request access to the user’s phone number and avatar: ```python SOCIAL_AUTH_SEZNAM_OAUTH2_SCOPE = ['contact-phone', 'avatar'] ``` ## User ID Seznam recommends the use of `oauth_user_id` as the user identifier instead of mutable data such as `username` or `email` because using mutable identifiers can pose security risks if the user changes them. For that reason `oauth_user_id` is used by default, but for compatibility with enterprise backend versions or other use cases, you can override this behavior by configuring the ID key via settings: ```python SOCIAL_AUTH_SEZNAM_OAUTH2_ID_KEY = 'id' ``` See the [Configurable User ID Key](../configuration/settings.html#configurable-user-id-key) documentation for more information about this feature. # backends/shopify.html.md # Shopify ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `shopify` | `social_core.backends.shopify.ShopifyOAuth2` | Shopify uses OAuth 2 for authentication. To use this backend, you must: - Install the [Shopify python library](https://github.com/Shopify/shopify_python_api): ```default pip install --upgrade ShopifyAPI ``` - Register a new application at [Shopify Partners](http://www.shopify.com/partners) - Configure your Shopify app to use the application URL of https://[your domain]/login/shopify/ - Configure your Shopify app to use the callback URL of https://[your domain]/complete/shopify/ - If you’re using Django, add the backend to your AUTHENTICATION_BACKENDS configuration: ```default AUTHENTICATION_BACKENDS = ( ..., 'social_core.backends.shopify.ShopifyOAuth2', ..., ) ``` - fill `API Key` and `Shared Secret` values in your django settings: ```default SOCIAL_AUTH_SHOPIFY_KEY = '' SOCIAL_AUTH_SHOPIFY_SECRET = '' ``` - fill the scope permissions that you require into the settings [Shopify API](http://api.shopify.com/authentication.html#scopes): ```default SOCIAL_AUTH_SHOPIFY_SCOPE = ['write_script_tags', 'read_orders', 'write_customers', 'read_products'] ``` - If you’d like to, you can set your desired Shopify API version in your settings: ```default SOCIAL_AUTH_SHOPIFY_API_VERSION = '2020-10' ``` [ShopifyAPI 5.0.0](https://github.com/Shopify/shopify_python_api#-breaking-change-notice-for-version-500-) introduced a non backward compatible change in order to support Shopify API versioning. The backend will default to value 2019-04 but it’s possible to override the default with the following setting: ```default SOCIAL_AUTH_SHOPIFY_API_VERSION = 'unstable' ``` # backends/simplelogin.html.md # SimpleLogin ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------------------| | `simplelogin` | `social_core.backends.simplelogin.SimpleLoginOAuth2` | SimpleLogin uses OAuth 2.0 for Authentication. - On your project settings, you should add SimpleLogin on your `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.simplelogin.SimpleLoginOAuth2', ) ``` - Register a new app at [SimpleLogin App](https://app.simplelogin.io). By default, SimpleLogin whitelists `localhost` so your app should work locally. Please set the callback URL to `http://example.com/complete/simplelogin/` replacing `example.com` with your domain when you deploy your web app to production. - Add these values of `Client ID` and `Client Secret` from SimpleLogin in your project settings file. The `Client ID` should be added on `SOCIAL_AUTH_SIMPLELOGIN_KEY` and the `Client Secret` should be added on `SOCIAL_AUTH_SIMPLELOGIN_SECRET`: ```default SOCIAL_AUTH_SIMPLELOGIN_KEY = 'client-id' SOCIAL_AUTH_SIMPLELOGIN_SECRET = 'very-secret' ``` # backends/sketchfab.html.md # Sketchfab ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------------| | `sketchfab` | `social_core.backends.sketchfab.SketchfabOAuth2` | Sketchfab uses OAuth 2 for authentication. To use: - Follow the steps at [Sketchfab Oauth](https://sketchfab.com/developers/oauth), and ask for an `Authorization code` grant type. - Fill the `Client id/key` and `Client Secret` values you received in your django settings: ```default SOCIAL_AUTH_SKETCHFAB_KEY = '' SOCIAL_AUTH_SKETCHFAB_SECRET = '' ``` # backends/slack.html.md # Slack ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `slack` | `social_core.backends.slack.SlackOAuth2` | Slack - Register a new application at [Slack](https://api.slack.com/applications), set the callback URL to `http://example.com/complete/slack/` replacing `example.com` with your domain. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_SLACK_KEY = '' SOCIAL_AUTH_SLACK_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_SLACK_SCOPE = [...] ``` See auth scopes at [Slack OAuth docs](https://api.slack.com/docs/oauth). - Limiting by team is possible by: ```default SOCIAL_AUTH_SLACK_TEAM = '' ``` # backends/soundcloud.html.md # SoundCloud ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `soundcloud` | `social_core.backends.soundcloud.SoundcloudOAuth2` | SoundCloud uses OAuth2 for its auth mechanism. - Register a new application at [SoundCloud App Registration](http://soundcloud.com/you/apps/new), set your application name, website and redirect URI. - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_SOUNDCLOUD_KEY = '' SOCIAL_AUTH_SOUNDCLOUD_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_SOUNDCLOUD_SCOPE = [...] ``` Possible scope values are \* or non-expiring according to their [/connect documentation](http://developers.soundcloud.com/docs/api/reference#connect). Check the rest of their doc at [SoundCloud Developer Documentation](http://developers.soundcloud.com/docs). # backends/spotify.html.md # Spotify ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `spotify` | `social_core.backends.spotify.SpotifyOAuth2` | Spotify supports OAuth 2. - Register a new application at [Spotify Web API](https://developer.spotify.com/spotify-web-api), and follow the instructions below. ## OAuth2 Add the Spotify OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.spotify.SpotifyOAuth2', ... ) ``` - Fill `App Key` and `App Secret` values in the settings: ```default SOCIAL_AUTH_SPOTIFY_KEY = '' SOCIAL_AUTH_SPOTIFY_SECRET = '' ``` # backends/stackoverflow.html.md # Stackoverflow ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |-----------------|----------------------------------------------------------| | `stackoverflow` | `social_core.backends.stackoverflow.StackoverflowOAuth2` | Stackoverflow uses OAuth 2.0 - “Register For An App Key” at the [Stack Exchange API](https://api.stackexchange.com/) site. Set your OAuth domain and application website settings. - Add the `Client Id`, `Client Secret` and `API Key` values in settings: ```default SOCIAL_AUTH_STACKOVERFLOW_KEY = '' SOCIAL_AUTH_STACKOVERFLOW_SECRET = '' SOCIAL_AUTH_STACKOVERFLOW_API_KEY = '' ``` - You can ask for extra permissions with: ```default SOCIAL_AUTH_STACKOVERFLOW_SCOPE = [...] ``` # backends/steam.html.md # Steam OpenID ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `steam` | `social_core.backends.steam.SteamOpenId` | Steam OpenID works quite straightforward, but to retrieve some user data (known as `player` on Steam API) a Steam API Key is needed. The backend validates the asserted OpenID identity URL and extracts the Steam ID from it. The generic `ID_KEY` setting does not apply to this protocol-derived identifier. Configurable settings: 1. Supply a Steam API Key from [Steam Dev](http://steamcommunity.com/dev/apikey) 2. Fill key in your project settings: ```default SOCIAL_AUTH_STEAM_API_KEY = '...' ``` 3. To save `player` data provided by Steam into `extra_data`: ```default SOCIAL_AUTH_STEAM_EXTRA_DATA = ['player'] ``` 4. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.steam.SteamOpenId', ... ) ``` # backends/stocktwits.html.md # StockTwits ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------------| | `stocktwits` | `social_core.backends.stocktwits.StocktwitsOAuth2` | StockTwits uses OAuth 2 for authentication. - Register a new application at [https://stocktwits.com/developers/apps](https://stocktwits.com/developers/apps) - Set the Website URL to [http://[your](http://[your) domain]/ - fill `Consumer Key` and `Consumer Secret` values in your django settings: ```default SOCIAL_AUTH_STOCKTWITS_KEY = '' SOCIAL_AUTH_STOCKTWITS_SECRET = '' ``` # backends/strava.html.md # Strava ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `strava` | `social_core.backends.strava.StravaOAuth` | Strava uses OAuth v2 for Authentication. - Register a new application at the [Strava API](https://www.strava.com/settings/api), and - fill `Client ID` and `Client Secret` from strava.com values in the settings: ```default SOCIAL_AUTH_STRAVA_KEY = '' SOCIAL_AUTH_STRAVA_SECRET = '' ``` - extra scopes can be defined by using: ```default SOCIAL_AUTH_STRAVA_SCOPE = ['view_private'] ``` # backends/stripe.html.md # Stripe ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `stripe` | `social_core.backends.stripe.StripeOAuth2` | Stripe uses OAuth2 for its authorization service. To setup Stripe backend: - Register a new application at [Stripe App Creation](https://manage.stripe.com/#account/applications/settings), and - Grab the `client_id` value in `Applications` tab and fill the `App Id` setting: ```default SOCIAL_AUTH_STRIPE_KEY = 'ca_...' ``` - Grab the `Test Secret Key` in the `API Keys` tab and fill the `App Secret` setting: ```default SOCIAL_AUTH_STRIPE_SECRET = '...' ``` - Define `SOCIAL_AUTH_STRIPE_SCOPE` with the desired scope (options are `read_only` and `read_write`): ```default SOCIAL_AUTH_STRIPE_SCOPE = ['read_only'] ``` - Add the needed backend to `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.stripe.StripeOAuth2', ... ) ``` More info on Stripe OAuth2 at [Integrating OAuth](https://stripe.com/docs/connect/oauth). # backends/suse.html.md # SUSE ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `opensuse` | `social_core.backends.suse.OpenSUSEOpenId` | This section describes how to setup the different services provided by SUSE and openSUSE. ## openSUSE OpenID openSUSE OpenID works straightforward, not settings are needed. Domains or emails whitelists can be applied too, check the [whitelists](../configuration/settings.html#whitelists) settings for details. The backend uses the verified OpenID identity URL for account association. Associations created by older social-core releases used `nickname` and migrate on the next successful authentication. # backends/taobao.html.md # Taobao OAuth ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `taobao` | `social_core.backends.taobao.TAOBAOAuth` | Taobao OAuth 2.0 workflow. - Register a new application at Open [Open Taobao](http://open.taobao.com). - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_TAOBAO_KEY = '' SOCIAL_AUTH_TAOBAO_SECRET = '' ``` By default `token` is stored in `extra_data` field. # backends/telegram.html.md # Telegram ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `telegram` | `social_core.backends.telegram.TelegramAuth` | Telegram uses a widget-based authentication method for login. - Create a bot using [BotFather](https://t.me/botfather) on Telegram to get a bot token. - Add the Telegram backend to `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.telegram.TelegramAuth', ... ) ``` - Fill the `Bot Token` value in the settings: ```default SOCIAL_AUTH_TELEGRAM_BOT_TOKEN = '' ``` - Add the Telegram Login Widget to your login page. The widget should be configured to send authentication data to your callback URL, which should be something like `http://example.com/complete/telegram/` replacing `example.com` with your domain. - The Telegram Login Widget can be added using the following HTML: ```default ``` Replace `YOUR_BOT_USERNAME` with your bot’s username (without the @ symbol) and update the `data-auth-url` to match your domain. - The authentication process verifies the data integrity using HMAC-SHA256 with the bot token. Authentication data is considered valid for 24 hours from the `auth_date` timestamp. - The backend extracts the following user information: - User ID (required) - Username - First name - Last name - Photo URL (if available) # backends/trello.html.md # Trello ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `trello` | `social_core.backends.trello.TrelloOAuth` | Trello provides OAuth1 support for their authentication process. Accounts are associated by Trello’s stable member `id`. Associations created by older social-core releases used `username` and migrate on the next successful authentication. In order to enable it, follow: - Generate an Application Key pair at [Trello Developers API Keys](https://trello.com/1/appKey/generate) - Fill **Consumer Key** and **Consumer Secret** settings: ```default SOCIAL_AUTH_TRELLO_KEY = '...' SOCIAL_AUTH_TRELLO_SECRET = '...' ``` There are also two optional settings: - your app name, otherwise the authorization page will say “Let An unknown application use your account?”: ```default SOCIAL_AUTH_TRELLO_APP_NAME = 'My App' ``` - the expiration period, social auth defaults to ‘never’, but you can change it: ```default SOCIAL_AUTH_TRELLO_EXPIRATION = '30days' ``` # backends/tripit.html.md # TripIt ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `tripit` | `social_core.backends.tripit.TripItOAuth` | TripIt offers per application keys named `API Key` and `API Secret`. To enable TripIt these two keys are needed. Further documentation at [TripIt Developer Center](https://www.tripit.com/developer): - Register a new application at [TripIt App Registration](https://www.tripit.com/developer/create), - fill **API Key** and **API Secret** values: ```default SOCIAL_AUTH_TRIPIT_KEY = '' SOCIAL_AUTH_TRIPIT_SECRET = '' ``` # backends/tumblr.html.md # Tumblr ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `tumblr` | `social_core.backends.tumblr.TumblrOAuth` | Tumblr uses OAuth 1.0a for authentication. The backend identifies an account by the UUID of its primary blog. The blog name remains available as the local username but is not used for account binding because Tumblr names can change and be reused. - Register a new application at [http://www.tumblr.com/oauth/apps](http://www.tumblr.com/oauth/apps) - Set the `Default callback URL` to [http://[your](http://[your) domain]/ - fill `OAuth Consumer Key` and `Secret Key` values in your Django settings: ```default SOCIAL_AUTH_TUMBLR_KEY = '' SOCIAL_AUTH_TUMBLR_SECRET = '' ``` # backends/twilio.html.md # Twilio Connect The Twilio backend links a Twilio Connect authorization to an existing local user. It is not an authentication backend and cannot be used to create users, sign users in, or recover access to an account. #### WARNING The local user must be authenticated before starting the connection. The same authenticated user must complete it. Twilio documents Connect as an authorization mechanism and recommends placing the Connect button behind application authentication. ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `twilio` | `social_core.backends.twilio.TwilioAuth` | ## Configuration - Register a new application using [Twilio Connect](https://www.twilio.com/docs/iam/connect). - Fill `SOCIAL_AUTH_TWILIO_KEY` and `SOCIAL_AUTH_TWILIO_SECRET` in the settings: ```default SOCIAL_AUTH_TWILIO_KEY = '' SOCIAL_AUTH_TWILIO_SECRET = '' ``` - Add the backend to Django’s `SOCIAL_AUTH_AUTHENTICATION_BACKENDS` setting: ```default 'social_core.backends.twilio.TwilioAuth', ``` ## Initiating the connection Framework integrations must pass their current user to `social_core.actions.do_auth()`. Use an integration release that supports the authentication initiation hook, or make the equivalent call in a custom authenticated view: ```default do_auth(request.backend, user=request.user) ``` For Django, initiate the connection with the CSRF-protected POST endpoint while the local user is signed in: ```default
{% csrf_token %}
``` The backend binds the callback state to the initiating local user. Anonymous initiation, anonymous completion, completion by another user, and callback replay are rejected. A successful callback creates or reuses the `twilio` social association for the current user; it does not log that user in again. ## Security limitations Twilio returns `AccountSid` as a browser-delivered query parameter without a signature or server-side authorization-code exchange. The backend can prevent that value from authenticating a local user, but it cannot prove that the current browser controls the returned Twilio account. An authenticated user who knows a valid, locally unassociated Connect SID could submit it during their own association flow. Treat Connect SIDs as sensitive user data, request only the Twilio permissions the application needs, and do not use the association as proof of Twilio account ownership. A Twilio API request can confirm that a SID is currently usable by the Connect App, but cannot bind it to the browser completing the flow. Configure and process Twilio’s Deauthorize URL so revoked Connect access also disables the corresponding local integration. # backends/twitch.html.md # Twitch ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------------------| | `twitch` | `social_core.backends.twitch.TwitchOpenIdConnect` | | `twitch` | `social_core.backends.twitch.TwitchOAuth2` | Twitch works similar to Facebook (OAuth). - Register a new application in the [connections tab](http://www.twitch.tv/settings/connections) of your Twitch settings page, set the callback URL to `http://example.com/complete/twitch/` replacing `example.com` with your domain. - Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_TWITCH_KEY = '' SOCIAL_AUTH_TWITCH_SECRET = '' ``` - Also it’s possible to define extra permissions with: ```default SOCIAL_AUTH_TWITCH_SCOPE = [...] ``` # backends/twitter.html.md # X (formerly Twitter) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------------| | `twitter` | `social_core.backends.twitter.TwitterOAuth` | Twitter offers per application keys named `Consumer Key` and `Consumer Secret`. To enable Twitter these two keys are needed. Further documentation at [Twitter development resources](https://dev.twitter.com/oauth): - Register a new application at [Twitter App Creation](https://apps.twitter.com/apps/new), - Check the **Allow this application to be used to Sign in with Twitter** checkbox. If you don’t check this box, Twitter will force your user to login every time. - Fill **Consumer Key** and **Consumer Secret** values: ```default SOCIAL_AUTH_TWITTER_KEY = '' SOCIAL_AUTH_TWITTER_SECRET = '' ``` - You need to specify an URL callback or the OAuth will raise a “403 Client Error”. The callback URL should be something like “[https://example.com/complete/twitter](https://example.com/complete/twitter)” - You can request user’s Email address (consult [Twitter verify credentials](https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials)), the parameter is sent automatically, but the application needs to be whitelisted in order to get a valid value. - You’ll need to apply for Elevated access via the Developer Portal, see [Twitter access levels](https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api#v2-access-level) for more info. Twitter usually fails with a 401 error when trying to call the request-token URL, this is usually caused by server datetime errors (check miscellaneous section). Installing `ntp` and syncing the server date with some pool does the trick. # backends/twitter_oauth2.html.md # X OAuth 2 ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |------------------|-----------------------------------------------------| | `twitter-oauth2` | `social_core.backends.twitter_oauth2.TwitterOAuth2` | Twitter offers per application keys named `Client ID` and `Client Secret`. To enable Twitter these two keys are needed. Further documentation at [Twitter development resources](https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code): - Register a new application at [Twitter App Creation](https://developer.twitter.com/en/portal/dashboard), - Fill **Client ID** and **Client Secret** values: ```default SOCIAL_AUTH_TWITTER_OAUTH2_KEY = '' SOCIAL_AUTH_TWITTER_OAUTH2_SECRET = '' ``` - You can specify PKCE challenge method following: ```default SOCIAL_AUTH_TWITTER_OAUTH2_PKCE_CODE_CHALLENGE_METHOD = '' ``` The possible values for configuration are `s256` and `plain`. By default, `s256` is set. You can see more information about PKCE at [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). - You need to specify an URL callback or the OAuth will raise a “403 Client Error”. The callback URL should be something like “[https://example.com/complete/twitter-oauth2](https://example.com/complete/twitter-oauth2)” # backends/uber.html.md # Uber ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `uber` | `social_core.backends.uber.UberOAuth2` | Uber uses OAuth v2 for Authentication. - Register a new application at the [Uber API](https://developer.uber.com/dashboard), and follow the instructions below ## OAuth2 1. Add the Uber OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.uber.UberOAuth2', ... ) ``` 2. Fill `Client Id` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_UBER_KEY = '' SOCIAL_AUTH_UBER_SECRET = '' ``` 3. Scope should be defined by using: ```default SOCIAL_AUTH_UBER_SCOPE = ['profile', 'request'] ``` # backends/udata.html.md # Udata ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-----------------------------------------------| | `datagouv` | `social_core.backends.udata.DatagouvfrOAuth2` | ## Datagouvfr OAuth2 [Datagouvfr](https://www.data.gouv.fr/) supports OAuth2 for their API. In order to set it up: - Go get your [your API key](https://www.data.gouv.fr/fr/admin/me/) (previous account creation is required). - Fill **Consumer Key** and **Consumer Secret** values in settings: ```default SOCIAL_AUTH_DATAGOUVFR_KEY = '' SOCIAL_AUTH_DATAGOUVFR_SECRET = '' ``` - Add `'social_core.backends.udata.DatagouvfrOAuth2'` into your `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`. # backends/untappd.html.md # Untappd ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `untappd` | `social_core.backends.untappd.UntappdOAuth2` | Untappd uses OAuth v2 for Authentication, check the [official docs](https://untappd.com/api/docs). - Create an app by filling out the form here: [Add App](https://untappd.com/api/register?register=new) - Apps are approved on a one-by-one basis, so you’ll need to wait a few days to get your client ID and secret. - Fill `Client ID` and `Client Secret` values in the settings: ```default SOCIAL_AUTH_UNTAPPD_KEY = '' SOCIAL_AUTH_UNTAPPD_SECRET = '' ``` - Optionally include a `User Agent` to identify your calls to Untappd (this may become required in the future): ```default SOCIAL_AUTH_UNTAPPD_USER_AGENT = 'My Custom User Agent or App Name' ``` - Add the backend to the `AUTHENTICATION_BACKENDS` setting: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.untappd.UntappdOAuth2', ... ) ``` - Then you can start authentication from your templates with a POST form: ```default
{% csrf_token %}
``` # backends/upwork.html.md # Upwork ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `upwork` | `social_core.backends.upwork.UpworkOAuth` | Upwork supports only OAuth 1. - Register a new application at [Upwork Developers](https://www.upwork.com/services/api/apply). ## OAuth1 Add the Upwork OAuth backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.upwork.UpworkOAuth', ... ) ``` - Fill `App Key` and `App Secret` values in the settings: ```default SOCIAL_AUTH_UPWORK_KEY = '' SOCIAL_AUTH_UPWORK_SECRET = '' ``` **Note:** For more information please go to [Upwork API Reference](https://developers.upwork.com/?lang=python). # backends/username.html.md # Username Auth ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------------| | `username` | `social_core.backends.username.UsernameAuth` | [python-social-auth](https://github.com/python-social-auth) comes with an [UsernameAuth](https://github.com/python-social-auth/social-core/blob/master/social_core/backends/username.py) backend which comes handy when your site uses requires the plain old username and password authentication mechanism. Actually that’s a lie since the backend doesn’t handle password at all, that’s up to the developer to validate the password in and the proper place to do it is the pipeline, right after the user instance was retrieved or created. The reason to leave password handling to the developer is because too many things are really tied to the project, like the field where the password is stored, salt handling, password hashing algorithm and validation. So just add the pipeline functions that will do that following the needs of your project. ## Backend settings `SOCIAL_AUTH_USERNAME_FORM_URL = '/login-form/'` : Used to redirect the user to the login/signup form, it must have at least one field named `username`. Form submit should go to `/complete/username`, or if it goes to your view, then your view should complete the process calling `social_core.actions.do_complete`. `SOCIAL_AUTH_USERNAME_FORM_HTML = 'login_form.html'` : The template will be used to render the login/signup form to the user, it must have at least one field named `username`. Form submit should go to `/complete/username`, or if it goes to your view, then your view should complete the process calling `social_core.actions.do_complete`. ## Password handling Here’s an example of password handling to add to the pipeline: ```default from social_core.exceptions import AuthCredentialError def user_password(strategy, user, is_new=False, *args, **kwargs): if strategy.backend.name != 'username': return password = strategy.request_data()['password'] if is_new: user.set_password(password) user.save() elif not user.validate_password(password): # return {'user': None, 'social': None} raise AuthCredentialError( strategy.backend, code="credential_rejected", source="request", stage="pipeline", parameter="password", recovery="correct_input", ) ``` # backends/vault.html.md # Hashicorp Vault ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------------| | `vault` | `social_core.backends.vault.VaultOpenIdConnect` | The [Vault](https://www.vaultproject.io/) backend allows authentication against the OIDC [provider](https://www.vaultproject.io/docs/secrets/identity/oidc-provider) in Hashicorp [Vault](https://www.vaultproject.io/) version 1.9 and later. The backend class is VaultOpenIdConnect with name vault. A minimum configuration is: ```default SOCIAL_AUTH_VAULT_OIDC_ENDPOINT = 'https://vault.example.net:8200/v1/identity/oidc/provider/default' SOCIAL_AUTH_VAULT_KEY = '' SOCIAL_AUTH_VAULT_SECRET = '' ``` The remaining configuration will be auto-detected, by fetching: ```default /.well-known/openid-configuration ``` You may need to set `SOCIAL_AUTH_VAULT_VERIFY_SSL = False` if your Vault server does not have its certificate signed by a trusted CA (e.g. with LetsEncrypt), although this should only be used for testing and not in production. ## Vault OIDC configuration Vault 1.10 onwards includes a pre-defined provider “default”, key “default” and assignment “allow_all”. With Vault 1.9 you will need to create these objects explicitly. You can then create an OIDC client, and read it back to get the auto-generated client ID and secret: ```default vault write identity/oidc/client/my-app \ redirect_uris="https://www.example.com/callback" \ assignments="allow_all" \ key="default" \ id_token_ttl="30m" \ access_token_ttl="1h" vault read identity/oidc/client/my-app ``` ## Scopes Vault is very flexible with regard to configuring claims and scopes, so it’s up to you how you map entity and/or alias metadata to OIDC claims. Here is a suggestion, which exposes the entity name as “preferred_username” and takes the other claims from entity metadata: ```default vault write identity/oidc/scope/profile \ description="Provides user info" \ template='{ "preferred_username": {{identity.entity.name}}, "name": {{identity.entity.metadata.name}}, "given_name": {{identity.entity.metadata.given_name}}, "family_name": {{identity.entity.metadata.family_name}} }' vault write identity/oidc/scope/email \ description="Provides email address" \ template='{ "email": {{identity.entity.metadata.email}} }' vault write identity/oidc/scope/groups \ description="Provides a list of group names" \ template='{ "groups": {{identity.entity.groups.names}} }' ``` The Vault backend inherits defaults from `open_id_connect.py`. In particular, it looks for the username in the `preferred_username` claim. If you need to choose a different claim then you can do so: ```default SOCIAL_AUTH_VAULT_USERNAME_KEY = 'nickname' ``` The default set of scopes requested are “openid”, “profile” and “email”. You can request additional claims like this: ```default SOCIAL_AUTH_VAULT_SCOPE = ['groups'] ``` and you can remove the default scopes using: ```default SOCIAL_AUTH_VAULT_IGNORE_DEFAULT_SCOPE = True ``` # backends/vend.html.md # Lightspeed Retail (X-Series) ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|----------------------------------------| | `vend` | `social_core.backends.vend.VendOAuth2` | Vend supports OAuth 2. - Register a new application at [Vend Developers Portal](https://developers.vendhq.com/developer/applications) - Add the Vend OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.vend.VendOAuth2', ... ) ``` - Fill `App Key` and `App Secret` values in the settings: ```default SOCIAL_AUTH_VEND_OAUTH2_KEY = '' SOCIAL_AUTH_VEND_OAUTH2_SECRET = '' ``` More details on their [docs](https://developers.vendhq.com/documentation). # backends/vimeo.html.md # Vimeo ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `vimeo` | `social_core.backends.vimeo.VimeoOAuth1` | | `vimeo-oauth2` | `social_core.backends.vimeo.VimeoOAuth2` | Vimeo uses OAuth1 to grant access to their API. In order to get the backend running follow: - Register an application at [Vimeo Developer Portal](https://developer.vimeo.com/apps/new) filling the required settings. Ensure to fill `App Callback URL` field with `http:///complete/vimeo/` - Fill in the **Client Id** and **Client Secret** values in your settings: ```default SOCIAL_AUTH_VIMEO_KEY = '' SOCIAL_AUTH_VIMEO_SECRET = '' ``` - Specify scopes with: ```default SOCIAL_AUTH_VIMEO_SCOPE = [...] ``` - Add the backend to `AUTHENTICATION_BACKENDS`: ```default AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.vimeo.VimeoOAuth1', ... ) ``` # backends/vk.html.md # VK.com (former Vkontakte) ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |----------------|--------------------------------------------| | `vk-id` | `social_core.backends.vk.VKIDOAuth2` | | `vk-oauth2` | `social_core.backends.vk.VKOAuth2` | | `vk-app` | `social_core.backends.vk.VKAppOAuth2` | | `vk-openapi` | `social_core.backends.vk.VKontakteOpenAPI` | Use VK ID for applications registered with VK ID. The other backends support legacy VK integrations. Each backend has a separate provider name and settings; switching to `vk-id` does not migrate or automatically link existing `vk-oauth2` account associations. ## VK ID Register an application in the [VK ID application dashboard](https://id.vk.ru/account/) and configure its allowed redirect URI to match your application’s complete URL, for example `https://example.com/complete/vk-id/`. Follow the [VK ID integration guide](https://id.vk.ru/about/business/go/docs/ru/vkid/latest/vk-id/connection/start-integration/auth-without-sdk/auth-without-sdk-web) for application registration requirements. Add the backend to Django’s `AUTHENTICATION_BACKENDS` and set the application ID as the key: ```default AUTHENTICATION_BACKENDS = [ # Include your other authentication backends here. "social_core.backends.vk.VKIDOAuth2", ] SOCIAL_AUTH_VK_ID_KEY = "your-application-id" ``` The backend uses the `id.vk.ru` endpoints and requires PKCE with S256. It does not send a client secret. Keep sessions available between the start and complete requests so the backend can validate `state` and retrieve its code verifier. Do not disable PKCE or select the `plain` challenge method. Start authentication using a POST form: ```default
{% csrf_token %}
``` Request optional permissions using space-separated OAuth scopes: ```default SOCIAL_AUTH_VK_ID_SCOPE = ["email"] ``` The callback must supply nonempty `code`, `device_id`, and `state` values. Both flat query parameters and a JSON object in the `payload` parameter are supported. If both formats supply the same authentication field, their values must agree. The callback must belong to an authorization started by this backend; an independently initiated browser SDK flow will not have its session verifier. The backend retrieves user information server-side and stores the access token, refresh token, expiry, scope, device ID, and available ID token in `extra_data`. Authentication uses the server-provided user ID. An ID token is stored as token metadata; it is not used as a verified identity claim. VK ID does not provide a legacy `screen_name`. The normal pipeline generates a username unless configured otherwise, for example: ```default SOCIAL_AUTH_VK_ID_USERNAME_IS_FULL_EMAIL = True ``` ### Refresh tokens The backend stores the device ID and the registered redirect URI used during authorization alongside the tokens. The account’s `get_access_token()` method automatically refreshes expired tokens using these saved values: ```default access_token = social.get_access_token(strategy) ``` To refresh explicitly and persist rotated tokens, use: ```default social.refresh_token(strategy) ``` Explicit arguments override the saved values when needed: ```default social.refresh_token( strategy, device_id=social.extra_data["device_id"], redirect_uri="https://example.com/complete/vk-id/", ) ``` Refresh requests include a new state value, which is checked against the response. Refresh fails if no device ID is available. Direct calls to `backend.refresh_token()` must supply the device ID and the registered redirect URI because they do not have access to the account’s saved credentials. ## Legacy OAuth2 For an existing VK OAuth2 application, add `social_core.backends.vk.VKOAuth2` to `AUTHENTICATION_BACKENDS` and configure: ```default SOCIAL_AUTH_VK_OAUTH2_KEY = "your-application-id" SOCIAL_AUTH_VK_OAUTH2_SECRET = "your-application-secret" ``` Start authentication using a POST form: ```default
{% csrf_token %}
``` Optional permissions and the API version can be configured with: ```default SOCIAL_AUTH_VK_OAUTH2_SCOPE = [...] SOCIAL_AUTH_VK_OAUTH2_API_VERSION = "5.131" ``` See the [VK API access rights](https://dev.vk.com/en/reference/access-rights). ### Extra profile data The backend requests additional profile fields named in `EXTRA_DATA`. Entries can be field names, aliases, or aliases with a flag to discard empty values: ```default SOCIAL_AUTH_VK_OAUTH2_EXTRA_DATA = [ ("screen_name", "display_name"), ("photo_50", "avatar"), ("nickname", "nickname", True), ] ``` Here `screen_name` is the source field requested from VK and `display_name` is the key saved in the account’s `extra_data`. Alias names and discard flags are not sent as API fields. See the [VK API users.get documentation](https://dev.vk.com/en/method/users.get) for available fields. The backend requests `photo_50` for the default avatar. Its URL is also available as `photo` and `user_photo` in the profile response for backward compatibility. Existing `EXTRA_DATA` entries using either legacy name request `photo_50` and continue to save the same keys. ## Legacy application OAuth2 For a VK iframe application, add `social_core.backends.vk.VKAppOAuth2` to `AUTHENTICATION_BACKENDS` and configure: ```default SOCIAL_AUTH_VK_APP_KEY = "your-application-id" SOCIAL_AUTH_VK_APP_SECRET = "your-application-secret" ``` Set the iframe URL to your application’s complete URL, for example `https://example.com/complete/vk-app/`. The callback requires `is_app_user`, `viewer_id`, `access_token`, `api_id`, and a valid `auth_key`. The backend verifies the signature, retrieves the profile directly from VK, and checks that its user ID matches `viewer_id`. There is no need to configure an initial `getProfiles` request or supply `api_result`; browser-supplied profile data is ignored. Configure the application membership check with: ```default SOCIAL_AUTH_VK_APP_USERMODE = 2 ``` `1` checks the callback’s `is_app_user` value. `2` requests membership from VK using a signed `isAppUser` call and rejects authentication when membership cannot be confirmed. Omit the setting to skip the membership check; `0` does not disable it. If using the legacy iframe JavaScript SDK, load it over HTTPS: ```default ``` Serve the iframe application through the HTTPS URL registered with VK. ## Legacy OpenAPI Add `social_core.backends.vk.VKontakteOpenAPI` to `AUTHENTICATION_BACKENDS` and configure: ```default SOCIAL_AUTH_VK_OPENAPI_APP_ID = "your-application-id" SOCIAL_AUTH_VK_OPENAPI_SECRET = "your-application-secret" ``` The application ID is passed to the local authentication template as `VK_APP_ID`. Load the legacy OpenAPI SDK over HTTPS: ```default ``` Before completing authentication, your integration must place VK’s signed session cookie value in the strategy session under `vk_app_`. The backend reads it with `strategy.session_get()`, checks the signature against the application secret, and verifies that it has not expired. A browser cookie alone is insufficient unless your integration makes it available there. The complete request must also contain `id`. The authenticated identity comes from `mid` in the verified session, regardless of the request’s `id` value. See the [VK OpenAPI authorization documentation](https://dev.vk.com/en/api/open-api/getting-started) for the signed session format. # backends/weibo.html.md # Weibo OAuth ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `weibo` | `social_core.backends.weibo.WeiboOAuth2` | Weibo OAuth 2.0 workflow. - Register a new application at [Weibo](http://open.weibo.com). - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_WEIBO_KEY = '' SOCIAL_AUTH_WEIBO_SECRET = '' ``` By default `account id`, `profile_image_url` and `gender` are stored in extra_data field. The user name is used by default to build the user instance `username`, sometimes this contains non-ASCII characters which might not be desirable for the website. To avoid this issue it’s possible to use the Weibo `domain` which will be inside the ASCII range by defining this setting: ```default SOCIAL_AUTH_WEIBO_DOMAIN_AS_USERNAME = True ``` # backends/xing.html.md # XING ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|---------------------------------------| | `xing` | `social_core.backends.xing.XingOAuth` | XING uses OAuth1 for their auth mechanism, in order to enable the backend follow: - Register a new application at [XING Apps Dashboard](https://dev.xing.com/applications), - Fill **Consumer Key** and **Consumer Secret** values: ```default SOCIAL_AUTH_XING_KEY = '' SOCIAL_AUTH_XING_SECRET = '' ``` # backends/yahoo.html.md # Yahoo ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|------------------------------------------| | `yahoo-oauth2` | `social_core.backends.yahoo.YahooOAuth2` | Yahoo supports OAuth2 for their auth flow. OAuth 2.0 workflow, useful if you are planning to use Yahoo’s API. - Register a new application at [Yahoo Developer Center](https://developer.yahoo.com/), set your app domain and configure scopes (they can’t be overridden by application). - Add the Yahoo OAuth2 backend to your settings page: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.yahoo.YahooOAuth2', ... ) ``` - Fill `Consumer Key` and `Consumer Secret` values in the settings: ```default SOCIAL_AUTH_YAHOO_OAUTH2_KEY = '' SOCIAL_AUTH_YAHOO_OAUTH2_SECRET = '' ``` # backends/yammer.html.md # Microsoft Viva Engage ## Backend classes For Django, choose from these class paths for `AUTHENTICATION_BACKENDS`. For other integrations, use the same class paths in the framework-specific backend setting. | Backend name | Class path | |------------------|---------------------------------------------------| | `yammer` | `social_core.backends.yammer.YammerOAuth2` | | `yammer-staging` | `social_core.backends.yammer.YammerStagingOAuth2` | Yammer users OAuth2 for their auth mechanism, this application supports Yammer OAuth2 in production and staging modes. ## Production Mode In order to enable the backend, follow: - Register an application at [Client Applications](https://www.yammer.com/client_applications), set the `Redirect URI` to `http:///complete/yammer/` - Fill **Client Key** and **Client Secret** settings: ```default SOCIAL_AUTH_YAMMER_KEY = '...' SOCIAL_AUTH_YAMMER_SECRET = '...' ``` ## Staging Mode Staging mode is configured the same as `Production Mode`, but settings are prefixed with: ```default SOCIAL_AUTH_YAMMER_STAGING_* ``` # backends/zotero.html.md # Zotero ## Backend class For Django, add this class path to `AUTHENTICATION_BACKENDS`. For other integrations, use the same class path in the framework-specific backend setting. | Backend name | Class path | |----------------|-------------------------------------------| | `zotero` | `social_core.backends.zotero.ZoteroOAuth` | Zotero implements OAuth1 as their authentication mechanism for their Web API v3. 1. Go to the [Zotero app registration page](https://www.zotero.org/oauth/apps) to register your application. 2. Fill the **Client ID** and **Client Secret** in your project settings: ```default SOCIAL_AUTH_ZOTERO_KEY = '...' SOCIAL_AUTH_ZOTERO_SECRET = '...' ``` 3. Enable the backend: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( ... 'social_core.backends.zotero.ZoteroOAuth', ... ) ``` Further documentation at [Zotero Web API v3 page](https://www.zotero.org/support/dev/web_api/v3/start). # configuration/cherrypy.html.md # CherryPy Framework CherryPy framework is supported, it works but I’m sure there’s room for improvements. The implementation uses SQLAlchemy as ORM and expects some values accessible on `cherrypy.request` for it to work. At the moment the configuration is expected on `cherrypy.config` but ideally it should be an application configuration instead. Expected values are: `cherrypy.request.user` : Current logged in user, load it in your application on a `before_handler` handler. `cherrypy.request.db` : Current database session, again, load it in your application on a `before_handler`. ## Dependencies The CherryPy application depends on [sqlalchemy](http://www.sqlalchemy.org/), there’s no support for others ORMs yet. ## Installing From [pypi](http://pypi.python.org/pypi/social-auth-app-cherrypy/): ```default $ pip install social-auth-app-cherrypy ``` ## Enabling the application The application is defined on `social_cherrypy.views.CherryPyPSAViews`, register it in the preferred way for your project. Check the rest of the docs for the other settings like enabling authentication backends and backends keys. ## Models Setup The models are located in `social_cherrypy.models`. A reference to your `User` model is required to be defined in the project settings, it should be an import path, for example: ```default cherrypy.config.update({ 'SOCIAL_AUTH_USER_MODEL': 'models.User' }) ``` ## Login mechanism By default the application sets the session value `user_id`, this is a simple solution and it should be improved, if you want to provider your own login mechanism you can do it by defining the `SOCIAL_AUTH_LOGIN_METHOD` setting, it should be an import path to a callable, like this: ```default SOCIAL_AUTH_USER_MODEL = 'app.login_user' ``` And an example of this function: ```default def login_user(strategy, user): strategy.session_set('user_id', user.id) ``` Then, ensure to load the user in your application at `cherrypy.request.user`, for example: ```default def load_user(): user_id = cherrypy.session.get('user_id') if user_id: cherrypy.request.user = cherrypy.request.db.query(User).get(user_id) else: cherrypy.request.user = None cherrypy.tools.authenticate = cherrypy.Tool('before_handler', load_user) ``` # configuration/django.html.md # Django Framework Django framework has a little more support since this application was derived from [django-social-auth](https://github.com/omab/django-social-auth). Here are some details on configuring this application on Django. ## Installing From [pypi](http://pypi.python.org/pypi/social-auth-app-django/): ```default $ pip install social-auth-app-django ``` And for [MongoEngine](http://mongoengine.org) ORM: ```default $ pip install social-auth-app-django-mongoengine ``` Current `social-auth-app-django` releases follow supported Django versions and require Django 5.2 or newer and Python 3.10 or newer. ## Quickstart This quickstart covers the essential configuration to get social authentication working in your Django project. **1. Add to INSTALLED_APPS**: ```default INSTALLED_APPS = ( ... 'social_django', ) ``` **2. Add the exception middleware**: Add `SocialAuthExceptionMiddleware` to your existing `MIDDLEWARE` list, after the session, authentication, and message middleware: ```default MIDDLEWARE = [ ... 'social_django.middleware.SocialAuthExceptionMiddleware', ] ``` This is recommended so expected authentication failures, such as an expired login session or declined authorization, show a useful error page instead of an HTTP 500 response. No error URL is required; configure `SOCIAL_AUTH_LOGIN_ERROR_URL` if you prefer a redirect to your own error page. See [Exceptions Middleware](configuration/django.html.md#django-exception-middleware) for customization and reporting behavior. With `DEBUG = True`, exceptions propagate by default to aid debugging. Set `SOCIAL_AUTH_RAISE_EXCEPTIONS = False` to preview the error page during local development. **3. Configure authentication backends** (example for Google OAuth2): ```default AUTHENTICATION_BACKENDS = ( 'social_core.backends.google.GoogleOAuth2', 'django.contrib.auth.backends.ModelBackend', # Keep for username/password login ) ``` **4. Add OAuth credentials to settings.py**: This is where you configure your `client_id`, `client_secret`, and `scope` for each provider: ```default # Google OAuth2 SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'your-client-id.apps.googleusercontent.com' SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'your-client-secret' SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', ] ``` For other providers, the pattern is `SOCIAL_AUTH__KEY`, `SOCIAL_AUTH__SECRET`, and `SOCIAL_AUTH__SCOPE`. See [Backends](backends/index.html.md) for provider-specific settings. #### WARNING Never commit credentials to version control. Use environment variables instead: ```default import os SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ.get('GOOGLE_OAUTH2_KEY') SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ.get('GOOGLE_OAUTH2_SECRET') ``` **5. Add URLs to urls.py**: ```default urlpatterns = [ ... path('', include('social_django.urls', namespace='social')), ] ``` **6. Configure redirect URLs**: ```default LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/' ``` **7. Run migrations**: ```default python manage.py migrate ``` Upgrades that add identifier-key tracking must install compatible releases of both `social-auth-core` and `social-auth-app-django` before running this command. The Django migration adds a blank `id_key` to existing social associations; social-core then migrates those rows according to the policy in [the configurable user ID key documentation](configuration/settings.html.md#configurable-user-id-key). **8. Add login form in template**: ```default
{% csrf_token %}
``` #### NOTE **Database considerations**: SQLite has field length limitations that can cause issues. For production, use PostgreSQL or MySQL. If using MySQL InnoDB or SQLite, add: ```default SOCIAL_AUTH_UID_LENGTH = 223 ``` For additional configuration options, see [Configuration](configuration/settings.html.md). ## Register the application The [Django built-in app](https://github.com/python-social-auth/social-app-django) comes with two ORMs, one for default Django ORM and another for [MongoEngine](http://mongoengine.org) ORM. Add the application to `INSTALLED_APPS` setting, for default ORM: ```default INSTALLED_APPS = ( ... 'social_django', ... ) ``` And for [MongoEngine](http://mongoengine.org) ORM: ```default INSTALLED_APPS = ( ... 'social_django_mongoengine', ... ) ``` Also ensure to define the [MongoEngine](http://mongoengine.org) storage setting: ```default SOCIAL_AUTH_STORAGE = 'social_django_mongoengine.models.DjangoStorage' ``` ## Database The built-in models use Django’s native `JSONField` to store extracted `extra_data`. Sync the database to create needed models once you added `social_django` to your installed apps: ```default ./manage.py migrate ``` ## Authentication backends Add desired authentication backends to Django’s [AUTHENTICATION_BACKENDS](http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#authentication-backends) setting: ```default AUTHENTICATION_BACKENDS = ( 'social_core.backends.open_id.OpenIdAuth', 'social_core.backends.google.GoogleOAuth2', 'social_core.backends.twitter.TwitterOAuth', ... 'django.contrib.auth.backends.ModelBackend', ) ``` Take into account that backends **must** be defined in [AUTHENTICATION_BACKENDS](http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#authentication-backends) or Django won’t pick them when trying to authenticate the user. Don’t miss `django.contrib.auth.backends.ModelBackend` if using `django.contrib.auth` application or users won’t be able to login by username / password method. For more documentation about setting backends to specific social applications, please see the [Backends](backends/index.html.md). ### Logging in users from custom views When multiple authentication backends are configured, Django’s `django.contrib.auth.login()` needs to know which backend to store in the session. Pass its dotted import path as the `backend` argument, or use a user instance whose `backend` attribute was set by `authenticate()`. This attribute is not a model field: a user created directly or loaded again from the database does not automatically have it. For example, a custom account activation view using `ModelBackend` can log in the user after validating the activation token and activating the account: ```default from django.contrib.auth import login # Validate the activation token and activate the account before this call. login(request, user, backend='django.contrib.auth.backends.ModelBackend') ``` Use the backend appropriate for your authentication flow, and ensure it is listed in `AUTHENTICATION_BACKENDS`. Adding a `backend` parameter to your own view’s signature only helps if you pass it to `login()`. Without an explicit backend or `user.backend`, Django raises `ValueError` when more than one backend is configured, with the message `You have multiple authentication backends configured and therefore must provide the `backend` argument or set the `backend` attribute on the user.` `django.contrib.auth.authenticate()` has a different purpose: it checks credentials against the configured backends. For username/password login, use: ```default from django.contrib.auth import authenticate, login user = authenticate(request, username=username, password=password) if user is not None: login(request, user) ``` Do not pass a dotted import path as `backend` to `authenticate()` to select a backend. Its keyword arguments are forwarded to the authentication backends; social auth backends expect a backend instance for that argument. Passing a string can cause `AttributeError: 'str' object has no attribute 'name'`. The standard `social:complete` view selects the social backend automatically before calling `login()`, including when resuming an email validation pipeline. For details about Django’s backend selection, see [Selecting the authentication backend](https://docs.djangoproject.com/en/stable/topics/auth/default/#selecting-the-authentication-backend). ## URLs entries Add URLs entries: ```default urlpatterns = [ ... path("", include('social_django.urls', namespace="social")), ... ] ``` In case you need a custom namespace, this setting is also needed: ```default SOCIAL_AUTH_URL_NAMESPACE = 'social' ``` #### HINT In case you include the namespace from another namespace, you need to adjust the configuration accordingly to include the parent namespace: ```default SOCIAL_AUTH_URL_NAMESPACE = 'accounts:social' ``` ## Starting Login The `social:begin` view requires a `POST` request. Use a form and include the CSRF token in templates that start authentication. ## Templates Example of google-oauth2 backend usage in template: ```default
{% csrf_token %}
``` ## Template Context Processors There’s a context processor that will add backends and associations data to template context: ```default TEMPLATES = [ { ... 'OPTIONS': { ... 'context_processors': [ ... 'social_django.context_processors.backends', 'social_django.context_processors.login_redirect', ... ] } } ] ``` `backends` context processor will load a `backends` key in the context with four entries on it: `associated` : It’s a list of `UserSocialAuth` instances related with the currently logged in user. Will be empty if there’s no current user. `not_associated` : A list of available backend names not associated with the current user yet. If there’s no user logged in, it will be a list of all available backends. `backends` : A list of all available backend names. `metadata` : A dictionary of display titles and optional static icon paths, keyed by backend identifier. ### Backend display names and icons Backend classes expose `title` (a human-readable sign-in label) and `icon` (an optional bundled SVG filename). Their `name` remains the stable identifier used in routes, settings, and stored associations. Custom backends may override these attributes; absent titles fall back to `name` and absent icons to `None`. Register the icon finder after Django’s standard finders: ```default STATICFILES_FINDERS = [ "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", "social_django.finders.SocialAuthIconFinder", ] ``` Run `collectstatic` after installing or upgrading. Applications can override bundled assets by supplying the same `social_auth/icons/` path. Only provider logos are bundled. They retain their respective owners’ rights and branding terms; they are not relicensed under the Python library’s BSD license. See the packaged icon provenance notice for official artwork sources and branding references. Applications supply their own generic or fallback icons. The existing context processor adds `backends.metadata`, a dictionary keyed by backend identifier. Each value contains `title` and `icon`; `icon` is a static path or `None`, not a URL. For example: ```default {% load static %} {% for name, provider in backends.metadata.items %}
{% csrf_token %}
{% endfor %} ``` Existing backend and association lists retain their original formats. ## Personalized Configuration You can add (or remove) several features on the social auth pipeline. By default there are some pipelines on social_django: `social_details` - Get the information we can about the user and return it in a simple format to create the user instance later. On some cases the details are already part of the auth response from the provider, but sometimes this could hit a provider API. `social_names` - Fill missing name representations; see [Name normalization](pipeline.html.md#name-normalization). `social_uid` - Get the social uid from whichever service we’re authing thru. The uid is the unique identifier of the given user in the provider. `auth_allowed` - Verifies that the current auth process is valid within the current project, this is where emails and domains whitelists are applied (if defined). `social_user` - Checks if the current social-account is already associated in the site. `get_username`- Make up a username for this person, appends a random string at the end if there’s any collision. `create_user` - Create a user account if we haven’t found one yet. `associate_user` - Create the record that associated the social account with this user. `extra_data` - Populate the extra_data field in the social record with the values specified by settings (and the default ones like access_token, etc). `user_details` - Update the user record with any changed info from the auth service. Some other pipelines are available for use as well, but are not included by default: `associate_by_email` - Associate current auth with a user with the same email address in the DB. Obs: This pipeline entry is not 100% secure unless you know that the providers enabled enforce email verification on their side, otherwise a user can attempt to take over another user account by using the same (not validated) email address on some provider. Usage example: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.social_auth.associate_by_email', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` ## ORMs As detailed above the built-in Django application supports default ORM and [MongoEngine](http://mongoengine.org) ORM. When using [MongoEngine](http://mongoengine.org) make sure you’ve followed the instructions for [MongoEngine Django integration](http://mongoengine-odm.readthedocs.org/en/latest/django.html), as you’re now utilizing that user model. The MongoEngine_ backend was developed and tested with version 0.6.10 of MongoEngine_. Alternate storage models implementations currently follow a tight pattern of models that behave near or identical to Django ORM models. It is currently not decoupled from this pattern by any abstraction layer. If you would like to implement your own alternate, please see the `social_django.models` and `social_django_mongoengine.models` modules for guidance. ## Active users filtering By default the model allows only active users to authenticate. This can be customised by `SOCIAL_AUTH_ACTIVE_USERS_FILTER` setting which is passed as kwargs to the query set filter method. ```python SOCIAL_AUTH_ACTIVE_USERS_FILTER = {} ``` ```python SOCIAL_AUTH_ACTIVE_USERS_FILTER = {"deleted_account": False} ``` ## JSON field storage The current Django models use Django’s native `models.JSONField` for `extra_data` and partial pipeline data. No JSON field setting is needed for new installations. Older migrations still import `social_django.fields.JSONField` for migration compatibility. The historical `SOCIAL_AUTH_JSONFIELD_ENABLED`, `SOCIAL_AUTH_JSONFIELD_CUSTOM`, and `SOCIAL_AUTH_POSTGRES_JSONFIELD` settings are only relevant while running those legacy migrations. ## Exceptions Middleware A base middleware handles `SocialAuthBaseException` by redirecting to a configured error URL or rendering an error page. It supports both synchronous and asynchronous Django request handlers. Add it to `MIDDLEWARE`, after your session, authentication, and message middleware: ```python MIDDLEWARE = [ # ... 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'social_django.middleware.SocialAuthExceptionMiddleware', ] ``` To redirect failures to an application error page, configure: ```python SOCIAL_AUTH_LOGIN_ERROR_URL = '/login-error/' SOCIAL_AUTH_RAISE_EXCEPTIONS = False ``` The redirect uses the configured error transports described below. The default message is the safe exception message. A backend attached by the `psa()` decorator is available at `request.backend`; backend-specific settings take precedence over global settings. Without this middleware, Social Auth exceptions are left to Django’s exception handling and can produce an HTTP 500 response. ### Fallback error page When `SOCIAL_AUTH_LOGIN_ERROR_URL` is unset, `None`, or an empty string, the middleware renders `social_django/error.html` directly. It does not use flash messages or query parameters, so the page works even when session cookies are unavailable. Explicit exception propagation still takes precedence, as described under exception raising below. The response status depends on the failure: | Exception family or reason | HTTP status | |------------------------------------------------------------------------------|---------------| | `AuthInputError` | 400 | | `AuthSessionError`, `AuthCredentialError`, `AuthPolicyError`, `AuthCanceled` | 403 | | `AuthAssociationError` | 409 | | `AuthResponseError` | 502 | | `AuthProviderError`: connection, unavailability, rate limit, or custom codes | 503 | | `AuthProviderError`: `timeout` | 504 | | `AuthProviderError`: `tls_error` or `http_error` | 502 | | Configuration errors, unknown errors, or other base exceptions | 500 | The reason codes `response_expired` and `nonce_mismatch` override the family status with 403; `invalid_expiry` overrides it with 500. Other custom codes inherit the family’s status. Provider HTTP statuses are not forwarded directly. The bundled page shows the safe message and guidance selected from the suggested recovery action. Only `session_context_missing` adds a hint about session expiry, cookies, and restarting login in the same browser and container. These are possible causes, not a diagnosis. The page does not automatically retry authentication. Override `social_django/error.html` in your application’s templates to customize its presentation. The middleware supplies `message`, `error_code`, `error_source`, `error_stage`, and `error_recovery`; it does not supply the raw exception, provider diagnostics, or identifying context. Normal Django template context processors still apply. The response includes headers preventing caching. You can also subclass the middleware and replace its `MIDDLEWARE` entry with your subclass. The following methods accept `request` and `exception`: * `get_message()` customizes the message for redirects and rendered pages. * `get_redirect_uri()` selects the error redirect URL. * `get_error_status()` selects the rendered response’s HTTP status. * `render_error()` customizes the rendered response and its reporting. For example, an application can change the status used for explicit cancellation: ```python from social_core.exceptions import AuthCanceled from social_django.middleware import SocialAuthExceptionMiddleware class CustomExceptionMiddleware(SocialAuthExceptionMiddleware): def get_error_status(self, request, exception): if isinstance(exception, AuthCanceled): return 400 return super().get_error_status(request, exception) ``` Rendered 4xx failures are logged at warning level using safe classification fields, without tracebacks. Rendered 5xx failures are logged at error level with the original exception and traceback so server-side defects remain diagnosable. Tracebacks are included only in server logs, not in the rendered page. Rendering a 500 handles the exception instead of propagating it, so exception-based monitoring may no longer receive it. Configure monitoring for the logs or override `render_error()` to integrate your reporting. Unrelated exceptions still propagate through Django normally. ### Error Transports In traditional server-rendered Django applications, social authentication errors are stored in Django’s flash messages framework (`django.contrib.messages`) and rendered by server-side templates (e.g. `{% if messages %}`). However, in modern Single Page Applications (SPAs built with React, Vue, Angular, etc.) or hybrid architectures, login and authentication views are handled on the client side. When `django.contrib.messages` is installed (such as for the Django Admin), error messages default to session/cookie flash storage and are never surfaced on client-side rendered frontend login pages. To support SPAs and hybrid setups, `SocialAuthExceptionMiddleware` provides a configurable error transport mechanism via the `SOCIAL_AUTH_ERROR_TRANSPORT` setting. An `ErrorTransport` enum is available in `social_django.middleware`: ```python from social_django.middleware import ErrorTransport ``` The supported transport modes are: `ErrorTransport.MESSAGES` (or string `'messages'`) : *(Default)* Dispatches errors via `django.contrib.messages.error` tagged with `social-auth` and the backend name. This maintains 100% backward compatibility with standard Django applications. `ErrorTransport.QUERY` (or string `'query'`) : Appends the error message and backend name as URL query parameters to the redirect target (e.g. `LOGIN_ERROR_URL`), allowing client-side routers (such as Vue Router or React Router) to inspect query parameters (e.g., `$route.query` or `URLSearchParams`). Both transports can be configured together to support hybrid applications where both Django template views and client-side SPAs handle authentication errors. Configuration examples: ```python from social_django.middleware import ErrorTransport # SPA / Client-side frontend: deliver errors via URL query parameters SOCIAL_AUTH_ERROR_TRANSPORT = [ErrorTransport.QUERY] # or using string notation: # SOCIAL_AUTH_ERROR_TRANSPORT = 'query' # Hybrid application: deliver via both Django messages and URL query parameters SOCIAL_AUTH_ERROR_TRANSPORT = [ErrorTransport.MESSAGES, ErrorTransport.QUERY] # or using string notation: # SOCIAL_AUTH_ERROR_TRANSPORT = ['messages', 'query'] ``` The setting accepts an `ErrorTransport` enum instance, a string (case-insensitive), or an iterable (such as a list or tuple) containing enum values or strings. Fallback behavior: * If `ErrorTransport.MESSAGES` is enabled and `django.contrib.messages` is not installed or a `MessageFailure` occurs, the middleware automatically falls back to appending query parameters (unless `ErrorTransport.QUERY` is already active). * If an unrecognized transport value is supplied, the middleware safely falls back to the default `[ErrorTransport.MESSAGES]`. ### Query Parameter Customization When query parameter transport is active (or triggered via fallback), the redirect destination receives two query parameters: `message = ''` : Safe default message from the exception raised. Provider descriptions are retained in the exception’s diagnostic `detail` and are not sent to clients. `backend = ''` : Backend name that was used, or `unknown-backend` if unresolved. You can customize the query parameter keys globally or per-backend using Django settings: ```python SOCIAL_AUTH_ERROR_PARAM_NAME = 'error_msg' # Default is 'message' SOCIAL_AUTH_BACKEND_PARAM_NAME = 'auth_backend' # Default is 'backend' ``` Alternatively, if you subclass `SocialAuthExceptionMiddleware`, you can override the class attributes directly: ```python class CustomExceptionMiddleware(SocialAuthExceptionMiddleware): ERROR_PARAM_NAME = 'error_msg' BACKEND_PARAM_NAME = 'auth_backend' ``` URL query parameters are safely merged using `urllib.parse`: any existing query parameters are preserved, stale error/backend parameters are updated with the latest failure details, and URL fragments (such as `/login/#/auth-callback`) are preserved with query parameters placed before the hash. ### Backend-specific settings Error transports, error URLs, parameter names, and exception raising can all be configured on a per-backend basis using the `SOCIAL_AUTH__` pattern. Error transport per-backend: ```python # Default for all backends (Django messages) SOCIAL_AUTH_ERROR_TRANSPORT = [ErrorTransport.MESSAGES] # Specific to Facebook (SPA route using query parameters) SOCIAL_AUTH_FACEBOOK_ERROR_TRANSPORT = [ErrorTransport.QUERY] # Specific to Google OAuth2 (both messages and query parameters) SOCIAL_AUTH_GOOGLE_OAUTH2_ERROR_TRANSPORT = ['messages', 'query'] ``` Error URLs per-backend: ```python SOCIAL_AUTH_LOGIN_ERROR_URL = '/login-error/' # Default for all backends SOCIAL_AUTH_FACEBOOK_LOGIN_ERROR_URL = '/facebook-error/' # Specific to Facebook SOCIAL_AUTH_GOOGLE_OAUTH2_LOGIN_ERROR_URL = '/google-error/' # Specific to Google OAuth2 ``` Query parameter names per-backend: ```python SOCIAL_AUTH_FACEBOOK_ERROR_PARAM_NAME = 'fb_error' SOCIAL_AUTH_FACEBOOK_BACKEND_PARAM_NAME = 'fb_backend' ``` Exception raising per-backend: ```python SOCIAL_AUTH_RAISE_EXCEPTIONS = False # Default for all backends SOCIAL_AUTH_FACEBOOK_RAISE_EXCEPTIONS = True # Raise exceptions only for Facebook ``` This is particularly useful when you want different error handling strategies for different authentication providers, such as showing a custom error page for certain providers or raising exceptions for debugging specific backends while keeping others in production mode. Exception processing is disabled when the effective `RAISE_EXCEPTIONS` setting is true. Settings are checked in this order, and the first configured value wins: 1. `SOCIAL_AUTH__RAISE_EXCEPTIONS` (uppercase backend name, with hyphens replaced by underscores). 2. `SOCIAL_AUTH_RAISE_EXCEPTIONS`. 3. `RAISE_EXCEPTIONS`. 4. `DEBUG` as the default when none of these settings is configured. For example, `SOCIAL_AUTH_RAISE_EXCEPTIONS = False` enables handling even with `DEBUG = True`; a backend-specific true value overrides that global false value. ### Structured authentication errors See [Exceptions](exceptions.html.md#authentication-exceptions) for the exception families and recovery contract. The middleware uses safe default messages; provider diagnostics and identifying context are not included in client transports. Enable metadata in query transport (including message-storage fallback) with: ```python SOCIAL_AUTH_ERROR_INCLUDE_METADATA = True # Default: False ``` The redirect receives `error_code`, `error_source`, `error_stage`, and `error_recovery` alongside the configured message/backend parameters. Backend-specific settings are supported. Existing query parameters and fragments are preserved; stale metadata values are replaced when metadata is enabled. If a configured message/backend parameter name matches a metadata key, the configured parameter takes precedence and that metadata field is omitted. Applications should select their own messages and redirects from stable codes, and should decide reporting independently of suggested recovery actions. Subclasses overriding `dispatch_error` or `append_query_params` must accept the new optional `metadata` argument. ## Launch Bridge Endpoints When the standard `begin` view (`social:begin`) was made POST-only to protect against Cross-Site Request Forgery (CSRF) vulnerabilities, workflows that inherently rely on browser GET requests could no longer initiate authentication without disabling CSRF protections. Common scenarios impacted by this requirement include: * **Identity Provider (IdP) Initiated Login**: Enterprise Single Sign-On (SSO) platforms (such as Okta or Microsoft Entra ID / Azure AD) that initiate OpenID Connect (OIDC) authentication flows by navigating the user’s browser to an application initiation URL with an `iss` and `target_link_uri`. * **Single Page Application (SPA) & Frontend Redirects**: Frontend clients or same-origin apps that initiate login redirects via direct link navigation (`window.location.href = '/app-launch//'`) rather than building and submitting an HTML form with a CSRF token. Rather than weakening `social:begin` by re-allowing GET requests, `social-app-django` provides two dedicated, defense-in-depth bridge endpoints: 1. `idp_launch` (`/idp-launch//`): Designed for external OpenID Connect IdP-initiated login flows. 2. `app_launch` (`/app-launch//`): Designed for same-origin application and SPA login redirects with OpenID Connect backends. Both views bridge an incoming GET redirect into an auto-submitting POST request targeting `social:begin` with a valid Django CSRF token, while enforcing strict security checks before triggering the backend authentication pipeline. #### NOTE **OpenID Connect (OIDC) Backend Prerequisite**: Both `idp_launch` and `app_launch` strictly require an OpenID Connect backend (or a custom backend that provides a valid, RFC-compliant HTTPS ID token issuer via `backend.id_token_issuer()` or the `SOCIAL_AUTH__ID_TOKEN_ISSUER` setting). If either endpoint is accessed with a backend that does not support ID token issuer validation (such as non-OIDC OAuth 1.0 or OAuth 2.0 backends like Facebook, GitHub, or Twitter), or if the backend does not supply a valid HTTPS issuer URL, the launch bridge immediately rejects the request with HTTP 400 (`BadRequest`). ### Enabling Launch Bridges For security and backward compatibility, both launch bridge endpoints are **opt-in** and disabled by default. When an endpoint is accessed without being enabled, it returns an `Http404` (404 Not Found). To enable one or both bridges, configure `SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES` in your Django `settings.py`. The setting accepts the `LaunchBridge` enum from `social_django.constants` or equivalent string literals: ```python from social_django.constants import LaunchBridge # Default (disabled) — both endpoints return 404 SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = None # or [] # Enable both bridges SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = [LaunchBridge.APP, LaunchBridge.IDP] # Or using string literals: # SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = ['app_launch', 'idp_launch'] # Enable only App Launch (same-origin app/SPA redirects) SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = [LaunchBridge.APP] # SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = ['app_launch'] # Enable only IdP Launch (external IdP-initiated OIDC login) SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = [LaunchBridge.IDP] # SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES = ['idp_launch'] ``` ### Endpoint Behaviors and Security Architecture Both endpoints employ a layered defense model to protect users and your application: #### IdP Launch (`idp_launch`) Route: `/idp-launch//` (URL name: `social:idp_launch`) Designed to handle [OIDC IdP-initiated login per the OpenID Connect Core specification](https://openid.net/specs/openid-connect-core-1_0-36.html#ThirdPartyInitiatedLogin). Enforces 8 security layers: 1. **Opt-In Gate**: Raises `Http404` if `LaunchBridge.IDP` (or `'idp_launch'`) is not present in `SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES`. 2. **Framing Protection**: Injects an `X-Frame-Options: DENY` header and a Content Security Policy (CSP) `frame-ancestors 'none'` directive to prevent clickjacking attacks. 3. **Open Redirect Prevention**: Strictly validates the `target_link_uri` parameter against allowed hosts using `is_safe_url`. Untrusted or external destinations are discarded to prevent open redirect vulnerabilities. 4. **Parameter Whitelisting & Issuer Validation**: Strictly accepts only `iss` and `target_link_uri` query parameters. Validates `iss` against the backend’s configured ID token issuer(s) or alias whitelist. Requires a valid RFC-compliant HTTPS issuer; backends without issuer support reject requests with HTTP 400 (`BadRequest`). 5. **Authenticated Session Bypass**: If the requesting user is already authenticated in Django, the authentication roundtrip is skipped and the user is immediately redirected to the safe target destination. 6. **Fetch Metadata Validation**: Inspects `Sec-Fetch-Dest` and `Sec-Fetch-Mode` headers to detect suspicious framing or non-top-level navigation contexts. 7. **Manual Fallback**: Automatically disables JavaScript form auto-submission and presents the user with a manual confirmation button if framing or embedding is detected. 8. **CSRF Protection**: Generates and submits a POST form targeting `social:begin` with a fresh, valid Django CSRF token. #### App Launch (`app_launch`) Route: `/app-launch//` (URL name: `social:app_launch`) Designed for same-origin frontend or SPA redirects with OpenID Connect (OIDC) backends. Enforces 10 security layers: 1. **Opt-In Gate**: Raises `Http404` if `LaunchBridge.APP` (or `'app_launch'`) is not present in `SOCIAL_AUTH_ENABLE_LAUNCH_BRIDGES`. 2. **Backend Issuer Validation**: Requires the backend to provide a valid, RFC-compliant HTTPS ID token issuer (via `id_token_issuer()` or `SOCIAL_AUTH__ID_TOKEN_ISSUER`). Non-OIDC backends (such as Facebook or GitHub) or backends with non-HTTPS issuers immediately raise HTTP 400 (`BadRequest`). If an optional `iss` query parameter is provided, it is validated against the backend’s allowed issuers. 3. **Origin Validation**: Inspects `Sec-Fetch-Site` and requires it to be `same-origin` when present. 4. **Referer Validation**: Validates the `Referer` header against allowed hosts when present. 5. **Framing Protection**: Injects `X-Frame-Options: DENY` and CSP `frame-ancestors 'none'` headers. 6. **Open Redirect Prevention**: Validates the `next` query parameter against allowed hosts using `is_safe_url`. 7. **Authenticated Session Bypass**: Immediately redirects already-authenticated users to the safe `next` destination or `settings.LOGIN_REDIRECT_URL`. 8. **Fetch Metadata Validation**: Verifies request context using `Sec-Fetch-*` headers. 9. **Manual Fallback**: Falls back to user click confirmation if potential framing is detected. 10. **CSRF Protection**: Submits a POST form targeting `social:begin` with a valid Django CSRF token. ### Multi-Tenant and Multiple Issuer Support In multi-tenant OpenID Connect environments (or backends that accept multiple issuer identifiers), valid issuers can be configured in two ways: 1. **Custom Backends**: Backends where `id_token_issuer()` returns a `list[str]` or `tuple[str]`. 2. **Settings Whitelist**: The `SOCIAL_AUTH__ALLOWED_ID_TOKEN_ISSUERS` setting allows specifying additional permitted issuer URLs. For example, for a multi-tenant Okta or Entra ID backend: ```python SOCIAL_AUTH_OKTA_OAUTH2_ALLOWED_ID_TOKEN_ISSUERS = [ 'https://customer1.okta.com/oauth2/default', 'https://customer2.okta.com/oauth2/default', ] ``` In `app_launch`, the primary configured issuer is selected by default, or callers can pass a specific validated issuer query parameter (e.g. `?iss=https://customer1.okta.com/oauth2/default`). If the requested backend does not configure an issuer or if an unapproved `iss` parameter is supplied, the view returns HTTP 400 (`BadRequest`). ### Allowed Redirect Hosts Safe redirect URL validation for `next` and `target_link_uri` checks the host against `request.get_host()`, global settings, and backend-specific settings: ```python # Global allowed hosts for redirects SOCIAL_AUTH_ALLOWED_REDIRECT_HOSTS = ['app.example.com', 'portal.example.com'] # Backend-specific allowed hosts SOCIAL_AUTH_GOOGLE_OAUTH2_ALLOWED_REDIRECT_HOSTS = ['subdomain.example.com'] ``` ### Customizing the Launch Template (`launch.html`) Both bridge views render `social_django/launch.html`. To customize the appearance, loading animation, or branding during the transition, create a file named `social_django/launch.html` within your project’s `templates` directory (ensuring your template loader prioritizes project templates). #### Template Context Variables The view passes the following context variables to the template: `action_url` : The target URL for the POST submission, which resolves to the `social:begin` view for the requested backend (e.g., `/login//`). `params` : A dictionary containing whitelisted key-value parameters to forward to `social:begin` (such as `iss` and `next` / `target_link_uri`). These should be rendered as hidden input fields. `auto_submit` : A boolean indicating whether automatic JavaScript form submission is safe. When `False` (e.g. if the request context indicates framing), the template should render a manual confirmation button instead of auto-submitting. `csrf_token` : The standard Django CSRF token, required for POSTing to `social:begin`. #### Example Custom Template Here is an example of a branded, accessible custom template: ```html+django {# templates/social_django/launch.html #} Authenticating...
{% csrf_token %} {% for key, value in params.items %} {% endfor %} {% if auto_submit %}

Signing in, please wait...

{% else %}

Click below to continue signing in.

{% endif %}
{% if auto_submit %} {% endif %} ``` ## Django Admin The default application (not the [MongoEngine](http://mongoengine.org) one) contains an `admin.py` module that will be auto-discovered by the usual mechanism. But, by the nature of the application which depends on the existence of a user model, it’s easy to fall in a recursive import ordering making the application fail to load. This happens because the admin module will build a set of fields to populate the `search_fields` property to search for related users in the administration UI, but this requires the user model to be retrieved which might not be defined at that time. To avoid this issue define the following setting to circumvent the import error: ```default SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['field1', 'field2'] ``` For example: ```default SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['username', 'first_name', 'email'] ``` The fields listed **must** be user models fields. It’s also possible to define more search fields, not directly related to the user model by definig the following setting: ```default SOCIAL_AUTH_ADMIN_SEARCH_FIELDS = ['field1', 'field2'] ``` ## Authentication storage cleanup Schedule `manage.py clearsocial` regularly, for example hourly. It removes unused verification codes and partial pipelines older than `--age` days (default: 14), and expired OpenID associations and OpenID Connect nonces. Association expiry uses each record’s `issued` timestamp and `lifetime`; `--age` does not change this policy. Active associations and linked user accounts are preserved. Applications with their own scheduled tasks can call `social_django.models.Association.cleanup_expired()` directly. Expiry is checked during OIDC login validation even when scheduled cleanup has not run. When upgrading to nonce lifetime enforcement, stop old login-serving processes, apply the social-auth-app-django migrations, and start processes with the coordinated social-auth-core and social-auth-app-django versions. The migration gives existing OIDC nonce records with an empty secret, `issued=0`, and `lifetime=0` a 30-minute grace period. After that period, validation rejects them and the next cleanup removes them. Other storage integrations need their own equivalent upgrade conversion; see [Storage](storage.html.md). # configuration/flask.html.md # Flask Framework Flask reusable applications are tricky (or I’m not capable enough). Here are details on how to enable this application on Flask. ## Dependencies The Flask app does not depend on any storage backend by default. There’s support for [SQLAlchemy](http://www.sqlalchemy.org/), [MongoEngine](http://mongoengine.org) and [Peewee](http://docs.peewee-orm.com/en/latest/). ## Installing Install the flask core from [pypi](http://pypi.python.org/pypi/social-auth-app-flask/): ```default $ pip install social-auth-app-flask ``` Install any of the storage solutions: ```default $ pip install social-auth-app-flask-sqlalchemy $ pip install social-auth-app-flask-mongoengine $ pip install social-auth-app-flask-peewee ``` ## Enabling the application The applications define a [Flask Blueprint](http://flask.pocoo.org/docs/blueprints/), which needs to be registered once the Flask app is configured by: ```default from social_flask.routes import social_auth app.register_blueprint(social_auth) ``` For [MongoEngine](http://mongoengine.org) you need this setting: ```default SOCIAL_AUTH_STORAGE = 'social_flask_mongoengine.models.FlaskStorage' ``` For [Peewee](http://docs.peewee-orm.com/en/latest/) you need this setting: ```default SOCIAL_AUTH_STORAGE = 'social_flask_peewee.models.FlaskStorage' ``` ## Models Setup At the moment the models for [python-social-auth](https://github.com/python-social-auth) are defined inside a function because they need the reference to the current db session and the User model used on your project (check *User model reference* below). Once the Flask app and the database are defined, call `init_social` to register the models: ```default from social_flask_sqlalchemy.models import init_social init_social(app, session) ``` For [MongoEngine](http://mongoengine.org): ```default from social_flask_mongoengine.models import init_social init_social(app, session) ``` For [Peewee](http://docs.peewee-orm.com/en/latest/): ```default from social_flask_peewee.models import init_social init_social(app, session) ``` So far I wasn’t able to find another way to define the models on another way rather than making it as a side-effect of calling this function since the database is not available and `current_app` cannot be used on init time, just run time. ## User model reference The application keeps a reference to the User model used by your project, define it by using this setting: ```default SOCIAL_AUTH_USER_MODEL = 'foobar.models.User' ``` The value must be the import path to the User model. ## Global user The application expects the current logged in user accessible at `g.user`, define a handler like this to ensure that: ```default @app.before_request def global_user(): g.user = get_current_logged_in_user ``` ## Flask-Login The application works quite well with [Flask-Login](https://github.com/maxcountryman/flask-login), ensure to have some similar handlers to these: ```default @login_manager.user_loader def load_user(userid): try: return User.query.get(int(userid)) except (TypeError, ValueError): pass @app.before_request def global_user(): g.user = login.current_user # Make current user available on templates @app.context_processor def inject_user(): try: return {'user': g.user} except AttributeError: return {'user': None} ``` ## Remembering sessions The users session can be remembered when specified on login. The common implementation for this feature is to pass a parameter from the login form (`remember_me`, `keep`, etc), to flag the action. [Flask-Login](https://github.com/maxcountryman/flask-login) will mark the session as persistent if told so. [python-social-auth](https://github.com/python-social-auth) will check for a given name (`keep`) by default, but since providers won’t pass parameters back to the application, the value must be persisted in the session before the authentication process happens. So, the following setting is required for this to work: ```default SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['keep'] ``` It’s possible to override the default name with this setting: ```default SOCIAL_AUTH_REMEMBER_SESSION_NAME = 'remember_me' ``` Don’t use the value `remember` since that will clash with [Flask-Login](https://github.com/maxcountryman/flask-login) which pops the value from the session. Then just pass the parameter `keep=1` as a GET or POST parameter. ## Exceptions handling The Django application has a middleware (that fits in the framework architecture) to facilitate the different [exceptions](https://github.com/python-social-auth/social-core/blob/master/social_core/exceptions.py) handling raised by [python-social-auth](https://github.com/python-social-auth). The same can be accomplished (even in a simple way) in Flask by defining an [errorhandler](http://flask.pocoo.org/docs/api/#flask.Flask.errorhandler). For example the next code will redirect any social-auth exception to a `/socialerror` URL: ```default from social_core.exceptions import SocialAuthBaseException @app.errorhandler(500) def error_handler(error): if isinstance(error, SocialAuthBaseException): return redirect('/socialerror') ``` Be sure to set your debug and test flags to `False` when testing this on your development environment, otherwise the exception will be raised and error handlers won’t be called. # configuration/index.html.md # Configuration All the apps share the settings names, some settings for Django framework are special (like `AUTHENTICATION_BACKENDS`). Below there’s a main settings document detailing each configuration and its purpose, plus sections detailed for each framework and their particularities. Support for more frameworks will be added in the future, pull-requests are very welcome. Contents: * [Configuration](configuration/settings.html.md) * [Application setup](configuration/settings.html.md#application-setup) * [Settings name](configuration/settings.html.md#settings-name) * [Keys and secrets](configuration/settings.html.md#keys-and-secrets) * [Authentication backends](configuration/settings.html.md#authentication-backends) * [URLs options](configuration/settings.html.md#urls-options) * [User model](configuration/settings.html.md#user-model) * [Tweaking some fields length](configuration/settings.html.md#tweaking-some-fields-length) * [Username generation](configuration/settings.html.md#username-generation) * [Extra arguments on auth processes](configuration/settings.html.md#extra-arguments-on-auth-processes) * [OAuth2 provider URLs override](configuration/settings.html.md#oauth2-provider-urls-override) * [Configurable User ID Key](configuration/settings.html.md#configurable-user-id-key) * [Processing requests and redirects](configuration/settings.html.md#processing-requests-and-redirects) * [Whitelists](configuration/settings.html.md#whitelists) * [Miscellaneous settings](configuration/settings.html.md#miscellaneous-settings) * [Account disconnection](configuration/settings.html.md#account-disconnection) * [Django Framework](configuration/django.html.md) * [Installing](configuration/django.html.md#installing) * [Quickstart](configuration/django.html.md#quickstart) * [Register the application](configuration/django.html.md#register-the-application) * [Database](configuration/django.html.md#database) * [Authentication backends](configuration/django.html.md#authentication-backends) * [URLs entries](configuration/django.html.md#urls-entries) * [Starting Login](configuration/django.html.md#starting-login) * [Templates](configuration/django.html.md#templates) * [Template Context Processors](configuration/django.html.md#template-context-processors) * [Personalized Configuration](configuration/django.html.md#personalized-configuration) * [ORMs](configuration/django.html.md#orms) * [Active users filtering](configuration/django.html.md#active-users-filtering) * [JSON field storage](configuration/django.html.md#json-field-storage) * [Exceptions Middleware](configuration/django.html.md#exceptions-middleware) * [Launch Bridge Endpoints](configuration/django.html.md#launch-bridge-endpoints) * [Django Admin](configuration/django.html.md#django-admin) * [Authentication storage cleanup](configuration/django.html.md#authentication-storage-cleanup) * [Flask Framework](configuration/flask.html.md) * [Dependencies](configuration/flask.html.md#dependencies) * [Installing](configuration/flask.html.md#installing) * [Enabling the application](configuration/flask.html.md#enabling-the-application) * [Models Setup](configuration/flask.html.md#models-setup) * [User model reference](configuration/flask.html.md#user-model-reference) * [Global user](configuration/flask.html.md#global-user) * [Flask-Login](configuration/flask.html.md#flask-login) * [Remembering sessions](configuration/flask.html.md#remembering-sessions) * [Exceptions handling](configuration/flask.html.md#exceptions-handling) * [Pyramid Framework](configuration/pyramid.html.md) * [Dependencies](configuration/pyramid.html.md#dependencies) * [Installing](configuration/pyramid.html.md#installing) * [Enabling the application](configuration/pyramid.html.md#enabling-the-application) * [Models Setup](configuration/pyramid.html.md#models-setup) * [User model reference](configuration/pyramid.html.md#user-model-reference) * [Global user](configuration/pyramid.html.md#global-user) * [User login](configuration/pyramid.html.md#user-login) * [Social auth in templates context](configuration/pyramid.html.md#social-auth-in-templates-context) * [CherryPy Framework](configuration/cherrypy.html.md) * [Dependencies](configuration/cherrypy.html.md#dependencies) * [Installing](configuration/cherrypy.html.md#installing) * [Enabling the application](configuration/cherrypy.html.md#enabling-the-application) * [Models Setup](configuration/cherrypy.html.md#models-setup) * [Login mechanism](configuration/cherrypy.html.md#login-mechanism) * [Webpy Framework](configuration/webpy.html.md) * [Dependencies](configuration/webpy.html.md#dependencies) * [Installing](configuration/webpy.html.md#installing) * [Configuration](configuration/webpy.html.md#configuration) * [URLs](configuration/webpy.html.md#urls) * [Session](configuration/webpy.html.md#session) * [User model](configuration/webpy.html.md#user-model) * [Porting from django-social-auth](configuration/porting_from_dsa.html.md) * [Installed apps](configuration/porting_from_dsa.html.md#installed-apps) * [URLs](configuration/porting_from_dsa.html.md#urls) * [Porting settings](configuration/porting_from_dsa.html.md#porting-settings) * [Authentication backends](configuration/porting_from_dsa.html.md#authentication-backends) * [Session](configuration/porting_from_dsa.html.md#session) # configuration/porting_from_dsa.html.md # Porting from django-social-auth Being a derivative work from [django-social-auth](https://github.com/omab/django-social-auth), porting from it to [python-social-auth](https://github.com/python-social-auth) should be an easy task. Porting to others libraries usually is a pain, I’m trying to make this as easy as possible. ## Installed apps On [django-social-auth](https://github.com/omab/django-social-auth) there was a single application to add into `INSTALLED_APPS` plus a setting to define which ORM to be used (default or MongoEngine). Now the apps are split and there’s not need for that extra setting. When using the default ORM: ```default INSTALLED_APPS = ( ... 'social_django', ... ) ``` And when using MongoEngine: ```default INSTALLED_APPS = ( ... 'social_django_mongoengine', ... ) ``` The models table names were defined to be compatible with those used on [django-social-auth](https://github.com/omab/django-social-auth), so data is not needed to be migrated. ## URLs The URLs are namespaced, you can chose your namespace, the [example app](https://github.com/python-social-auth/social-examples/blob/master/example-django/example/urls.py) uses the `social` namespace. Replace the old include with: ```default urlpatterns = [ ... path('', include('social_django.urls', namespace='social')), ... ] ``` On templates use a namespaced URL in a POST form to start login: ```default
{% csrf_token %}
``` Account disconnection URL would be: ```default {% url 'social:disconnect_individual' provider, id %} ``` ## Porting settings All [python-social-auth](https://github.com/python-social-auth) settings are prefixed with `SOCIAL_AUTH_`, except for some exception on Django framework, `AUTHENTICATION_BACKENDS` remains the same for obvious reasons. All backends settings have the backend name included in the name, all uppercase and with dashes replaced with underscores. For example, the Google OAuth2 backend is named `google-oauth2`, so setting names related to that backend should start with `SOCIAL_AUTH_GOOGLE_OAUTH2_`. Keys and secrets are some mandatory settings needed for OAuth providers; to keep consistency the names follow the same naming convention: `*_KEY` for the application key, and `*_SECRET` for the secret. OAuth1 backends used to have `CONSUMER` in the setting name but not anymore. Following with the Google OAuth2 example: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '...' SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '...' ``` Remember that the name of the backend is needed in the settings, and names differ a little from backend to backend; for instance the [Facebook OAuth2 backend](https://github.com/python-social-auth/social-core/blob/master/social_core/backends/facebook.py#L17) name is `facebook`. So the settings should be: ```default SOCIAL_AUTH_FACEBOOK_KEY = '...' SOCIAL_AUTH_FACEBOOK_SECRET = '...' ``` ## Authentication backends Import path for authentication backends changed a little, there’s no more `contrib` module, there’s no need for it. Some backends changed the names to have some consistency. Check the backends, it should be easy to track the names changes. Examples of the new import paths: ```default AUTHENTICATION_BACKENDS = ( 'social_core.backends.open_id.OpenIdAuth', 'social_core.backends.google.GoogleOAuth2', 'social_core.backends.google.GoogleOAuth', 'social_core.backends.twitter.TwitterOAuth', 'social_core.backends.facebook.FacebookOAuth2', ) ``` ## Session Django stores the last authentication backend used in the user session as an import path; this can cause import troubles when porting since the old import paths aren’t valid anymore. Some solutions to this problem are: 1. Clean the session and force the users to login again in your site 2. Run a migration script that will update the authentication backend session value for each session in your database. This implies figuring out the new import path for each backend you have configured, which is the value used in `AUTHENTICATION_BACKENDS` setting. [@tomgruner](https://github.com/tomgruner) created a Gist [here](https://gist.github.com/tomgruner/5ce8bb1f4c55d17b5b25) that updates the value just for Facebook backend. A `template` for this script would look like this: ```default from django.contrib.sessions.models import Session BACKENDS = { 'social_auth.backends.facebook.FacebookBackend': 'social_core.backends.facebook.FacebookOAuth2' } for sess in Session.objects.iterator(): session_dict = sess.get_decoded() if '_auth_user_backend' in session_dict.keys(): # Change old backend import path from new backend import path if session_dict['_auth_user_backend'].startswith('social_auth'): session_dict['_auth_user_backend'] = BACKENDS[session_dict['_auth_user_backend']] new_sess = Session.objects.save(sess.session_key, session_dict, sess.expire_date) print('New session saved {}'.format(new_sess.pk)) ``` # configuration/pyramid.html.md # Pyramid Framework [Pyramid](http://www.pylonsproject.org/projects/pyramid/about) reusable applications are tricky (or I’m not capable enough). Here are details on how to enable this application on Pyramid. ## Dependencies The [Pyramid app](https://github.com/python-social-auth/social-app-pyramid) depends on [sqlalchemy](http://www.sqlalchemy.org/), there’s no support for others ORMs yet but pull-requests are welcome. ## Installing From [pypi](http://pypi.python.org/pypi/social-auth-app-pyramid/): ```default $ pip install social-auth-app-pyramid ``` ## Enabling the application The application can be scanned by `Configurator.scan()`, also it defines an `includeme()` in the `__init__.py` file which will add the needed routes to your application configuration. To scan it just add: ```default config.include('social_pyramid') config.scan('social_pyramid') ``` ## Models Setup At the moment the models for [python-social-auth](https://github.com/python-social-auth) are defined inside a function because they need the reference to the current DB instance and the User model used on your project (check *User model reference* below). Once the Pyramid application configuration and database are defined, call `init_social` to register the models: ```default from social_pyramid.models import init_social init_social(config, Base, DBSession) ``` So far I wasn’t able to find another way to define the models on another way rather than making it as a side-effect of calling this function since the database is not available and `current_app` cannot be used on initialization time, just run time. ## User model reference The application keeps a reference to the User model used by your project, define it by using this setting: ```default SOCIAL_AUTH_USER_MODEL = 'foobar.models.User' ``` The value must be the import path to the User model. ## Global user The application expects the current logged in user accessible at `request.user`, the example application ensures that with this handler: ```default def get_user(request): user_id = request.session.get('user_id') if user_id: user = DBSession.query(User)\ .filter(User.id == user_id)\ .first() else: user = None return user ``` The handler is added to the configuration doing: ```default config.add_request_method('example.auth.get_user', 'user', reify=True) ``` This is just a simple example, probably your project does it in a better way. ## User login Since the application doesn’t make any assumption on how you are going to login the users, you need to specify it. In order to do that, define these settings: ```default SOCIAL_AUTH_LOGIN_FUNCTION = 'example.auth.login_user' SOCIAL_AUTH_LOGGEDIN_FUNCTION = 'example.auth.login_required' ``` The first one must accept the strategy used and the user instance that was created or retrieved from the database, there you can set the user id in the session or cookies or whatever place used later to retrieve the id again and load the user from the database (check the snippet above in *Global User*). The second one is used to ensure that there’s a user logged in when calling the disconnect view. It must accept a `User` instance and return `True` or `False`. Check the [auth.py](https://github.com/python-social-auth/social-examples/blob/master/example-pyramid/example/auth.py) in the example application for details on how it’s done there. ## Social auth in templates context To access the social instances related to a user in the template context, you can do so by accessing the `social_auth` attribute in the user instance: ```default
  • ${social.provider}
  • ``` Also you can add the backends (associated and not associated to a user) by enabling this context function in your project: ```default from pyramid.events import subscriber, BeforeRender from social_pyramid.utils import backends @subscriber(BeforeRender) def add_social(event): request = event['request'] event.update(backends(request, request.user)) ``` That will load a dict with entries: ```default { 'associated': [...], 'not_associated': [...], 'backends': [...] } ``` The `associated` key will have all the associated `UserSocialAuth` instances related to the given user. `not_associated` will have the backends names not associated and backends will have all the enabled backends names. # configuration/settings.html.md # Configuration ## Application setup Once the application is installed (check [Installation](../installing.html)) define the following settings to enable the application behavior. Also check the sections dedicated to each framework for detailed instructions. ## Settings name Almost all settings are prefixed with `SOCIAL_AUTH_`, there are some exceptions for Django framework like `AUTHENTICATION_BACKENDS`. All settings can be defined per-backend by adding the backend name to the setting name, like `SOCIAL_AUTH_TWITTER_LOGIN_URL`. Settings discovery is done by reducing the name starting with the backend setting, then the app setting, and finally the global setting, for example: ```default SOCIAL_AUTH_TWITTER_LOGIN_URL SOCIAL_AUTH_LOGIN_URL LOGIN_URL ``` The backend name is generated from the `name` attribute from the backend class by uppercasing it and replacing `-` with `_`. ## Keys and secrets - Set up needed OAuth keys (see [OAuth](http://oauth.net/) section for details): ```default SOCIAL_AUTH_TWITTER_KEY = 'foobar' SOCIAL_AUTH_TWITTER_SECRET = 'bazqux' ``` OpenID backends don’t require keys usually, but some need some API Key to call any API on the provider. Check [Backends](../backends/index.html) sections for details. ## Authentication backends Register the backends you plan to use, on Django framework use the usual `AUTHENTICATION_BACKENDS` settings, for others, define `SOCIAL_AUTH_AUTHENTICATION_BACKENDS`: ```default SOCIAL_AUTH_AUTHENTICATION_BACKENDS = ( 'social_core.backends.open_id.OpenIdAuth', 'social_core.backends.google.GoogleOAuth2', 'social_core.backends.google.GoogleOAuth', 'social_core.backends.twitter.TwitterOAuth', 'social_core.backends.yahoo.YahooOAuth2', ... ) ``` ## URLs options These URLs are used on different steps of the auth process, some for successful results and others for error situations. `SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/logged-in/'` : Used to redirect the user once the auth process ended successfully. The value of the `next` request parameter is used if it was present `SOCIAL_AUTH_LOGIN_ERROR_URL = '/login-error/'` : URL where the user will be redirected in case of an error. With Django’s `SocialAuthExceptionMiddleware`, leaving this unset or empty renders the bundled error page instead. See [Django Framework](configuration/django.html.md) for status mappings and customization. The Django exception middleware does not fall back to `SOCIAL_AUTH_LOGIN_URL`. `SOCIAL_AUTH_LOGIN_URL = '/login-url/'` : Fallback login URL used by authentication actions when a more specific redirect URL is unavailable. It is not a fallback for Django’s exception middleware. `SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/new-users-redirect-url/'` : Used to redirect new registered users, will be used in place of `SOCIAL_AUTH_LOGIN_REDIRECT_URL` if defined. Note that the `next` request parameter is appended if present, if you want new users to go to next, you’ll need to do it yourself. `SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/new-association-redirect-url/'` : Like `SOCIAL_AUTH_NEW_USER_REDIRECT_URL` but for new associated accounts (user is already logged in). Used in place of `SOCIAL_AUTH_LOGIN_REDIRECT_URL` `SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = '/account-disconnected-redirect-url/'` : The user will be redirected to this URL when a social account is disconnected `SOCIAL_AUTH_INACTIVE_USER_URL = '/inactive-user/'` : Inactive users can be redirected to this URL when trying to authenticate. Successful URLs will default to `SOCIAL_AUTH_LOGIN_URL` while error URLs will fallback to `SOCIAL_AUTH_LOGIN_ERROR_URL`. ## User model `UserSocialAuth` instances keep a reference to the `User` model of your project, since this is not known, the `User` model must be configured by a setting: ```default SOCIAL_AUTH_USER_MODEL = 'foo.bar.User' ``` `User` model must have a `username` and `email` field, these are required. Also an `is_authenticated` and `is_active` boolean flags are recommended, these can be methods if necessary (must return `True` or `False`). If the model lacks them a `True` value is assumed. ## Tweaking some fields length Some databases impose limitations on index columns (like MySQL InnoDB). These limitations won’t play nice on some `UserSocialAuth` fields. To avoid such errors, define some of the following settings. `SOCIAL_AUTH_UID_LENGTH = ` : Used to define the max length of the field uid. A value of 223 should work when using MySQL InnoDB which impose a 767 bytes limit (assuming UTF-8 encoding). `SOCIAL_AUTH_NONCE_SERVER_URL_LENGTH = ` : `Nonce` model has a unique constraint over `('server_url', 'timestamp', 'salt')`, salt has a max length of 40, so `server_url` length must be tweaked using this setting. `SOCIAL_AUTH_ASSOCIATION_SERVER_URL_LENGTH = ` or `SOCIAL_AUTH_ASSOCIATION_HANDLE_LENGTH = ` : `Association` model has a unique constraint over `('server_url', 'handle')`, both fields lengths can be tweaked by these settings. ## Username generation Some providers return a username, others just an ID or email or first and last names. The application tries to build a meaningful username when possible but defaults to generating one if needed. A UUID is appended to usernames in case of collisions. Here are some settings to control username generation. `SOCIAL_AUTH_UUID_LENGTH = 16` : This controls the length of the UUID appended to usernames. `SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True` : If you want to use the full email address as the `username`, define this setting. `SOCIAL_AUTH_SLUGIFY_USERNAMES = False` : For those that prefer slugged usernames, the `get_username` pipeline can apply a slug transformation (code borrowed from Django project) by defining this setting to `True`. The feature is disabled by default to not force this option to all projects. `SOCIAL_AUTH_CLEAN_USERNAMES = True` : By default [a set of regular expressions](https://github.com/python-social-auth/social-core/blob/master/social_core/storage.py#L18-L19) are applied over usernames to clean them from usual undesired characters like spaces. Set this setting to `False` to disable this behavior. `SOCIAL_AUTH_CLEAN_USERNAME_FUNCTION = None` : Sometimes extra cleaning up of usernames is needed in order to fit properly in a project, this setting is used to point to a function that will be called with the current username value, the output will be used as the new username. This method can be called multiple times in case of a collision. The setting value must be in the format of an import path. ## Extra arguments on auth processes Some providers accept particular GET parameters that produce different results during the auth process, usually used to show different dialog types (mobile version, etc). You can send extra parameters on auth process by defining settings per backend, example to request Facebook to re-authenticate the user, define: ```default SOCIAL_AUTH_FACEBOOK_AUTH_EXTRA_ARGUMENTS = {'auth_type': 'reauthenticate'} ``` #### NOTE The `display` parameter (e.g., `{'display': 'touch'}`) was deprecated in Facebook Graph API v3.0+. Facebook now automatically detects mobile devices based on the user agent. If you’re using Graph API v3.0 or later, avoid using the `display` parameter as it will cause authentication errors. For other providers, just define settings in the form: ```default SOCIAL_AUTH__AUTH_EXTRA_ARGUMENTS = {...} ``` Also, you can send extra parameters on request token process by defining settings in the same way explained above but with this other suffix: ```default SOCIAL_AUTH__REQUEST_TOKEN_EXTRA_ARGUMENTS = {...} ``` ## OAuth2 provider URLs override By default, OAuth2 backends have hardcoded URLs for authorization and access token endpoints. However, these can be overridden via settings to support custom OAuth2 providers or alternate deployments of the same provider (e.g., OpenHistoricalMap instead of OpenStreetMap, or self-hosted instances). `SOCIAL_AUTH_AUTHORIZATION_URL` : Override the authorization URL for OAuth2 backends globally or per-backend. Example:
    ```default SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = 'https://auth.example.com/auth/realms/myrealm/protocol/openid-connect/auth' ``` `SOCIAL_AUTH_ACCESS_TOKEN_URL` : Override the access token URL for OAuth2 backends globally or per-backend. Example:
    ```default SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = 'https://auth.example.com/auth/realms/myrealm/protocol/openid-connect/token' ``` `SOCIAL_AUTH_REVOKE_TOKEN_URL` : Override the token revocation URL for OAuth2 backends globally or per-backend. Example:
    ```default SOCIAL_AUTH_GITHUB_REVOKE_TOKEN_URL = 'https://github.example.com/api/revoke' ``` These settings allow you to use backends with custom deployments. For example, to use the OpenStreetMap OAuth2 backend with OpenHistoricalMap: ```default SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_AUTHORIZATION_URL = 'https://www.openhistoricalmap.org/oauth2/authorize' SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_ACCESS_TOKEN_URL = 'https://www.openhistoricalmap.org/oauth2/token' ``` Note that backend-specific settings (with the backend name) take precedence over generic settings, following the same pattern as other settings in this library. ## Configurable User ID Key By default, mapping-based backends define an `ID_KEY` class attribute that specifies which field in the provider’s response should be used as the unique user identifier. This identifier is stored in the `UserSocialAuth.uid` field. However, some providers may return different user identifier fields depending on the API version, configuration, or deployment (e.g., enterprise vs. cloud versions). To support these scenarios, the `ID_KEY` can be configured per-backend via settings: `SOCIAL_AUTH__ID_KEY = 'field_name'` : Override the default ID key for a specific backend. The value should be the name of the field that contains the unique user identifier. For backends with nested responses, the field is read from the same nested object as the default identifier. Backend-specific prefixes, validation, fallbacks, and transformations still apply. An explicitly configured `ID_KEY` takes precedence over older backend-specific identifier selectors such as `USERNAME_AS_ID`, `USE_UNIQUE_USER_ID`, and `IDENTIFIED_BY_PERMANENT_ID`. An explicitly configured field must be present and non-empty in the provider data; otherwise authentication fails with `AuthResponseError` and `code="missing_claim"` rather than storing an ambiguous user identifier. Example: Configure Seznam backend to use `id` instead of the default `oauth_user_id`: ```default SOCIAL_AUTH_SEZNAM_OAUTH2_ID_KEY = 'id' ``` Example: Configure Keycloak backend to use `email` instead of the default `sub`: ```default SOCIAL_AUTH_KEYCLOAK_ID_KEY = 'email' ``` Example: Explicitly select the stable, application-specific `sub` claim for an Azure AD backend: ```default SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_ID_KEY = 'sub' ``` The generic OpenID backend and Steam derive the identifier from the asserted OpenID identity URL, so `ID_KEY` does not apply to them. The Ubuntu, openSUSE, and Yandex OpenID backends expose that protocol identifier as `identity_url` and allow an explicit override. The SAML backend uses the per-IdP `attr_user_permanent_id` mapping instead. See the [OpenID](backends/openid.html.md), [Steam](backends/steam.html.md), and [SAML](backends/saml.html.md) backend documentation. Associations store both the identifier value and the name of the provider field that supplied it. When a bundled backend changes to a more stable default, associations created by older versions have a blank identifier key. On the next successful authentication, social-core first attempts to prove the association using stable data stored in `extra_data`. By default it then falls back to the current value of the backend’s historical identifier and updates the association to the stable identifier. `SOCIAL_AUTH_ALLOW_UNVERIFIED_LEGACY_UID_MIGRATION = True` : Allow the compatibility fallback for legacy associations whose stable identity cannot be proved from stored provider data. This is enabled by default so unchanged existing users continue to authenticate.
    Set this to `False` to require stable stored data, an administrative data migration, or an authenticated reconnection. Backend-specific variants of the setting are supported. #### WARNING A legacy association remains keyed by its old identifier until it is migrated. With compatibility fallback enabled, the first provider identity to present that value can claim the migration. Deployments that cannot accept this one-time risk should disable unverified migration before upgrading and migrate associations administratively. Explicitly overriding `ID_KEY` with a mutable username, email address, UPN, or `preferred_username` keeps the corresponding backend vulnerable. Known unsafe overrides emit a warning, but remain supported for compatibility. Basic information is requested to the different providers in order to create a coherent user instance (with first and last name, email and full name), this could be too intrusive for some sites that want to ask users the minimum data possible. It’s possible to override the default values requested by defining any of the following settings, for Open Id providers: ```default SOCIAL_AUTH__IGNORE_DEFAULT_AX_ATTRS = True SOCIAL_AUTH__AX_SCHEMA_ATTRS = [ (schema, alias) ] ``` For OAuth backends: ```default SOCIAL_AUTH__IGNORE_DEFAULT_SCOPE = True SOCIAL_AUTH__SCOPE = [ ... ] ``` ## Processing requests and redirects The application issues several redirects and API calls. The following settings allow some tweaks to the behavior of these. `SOCIAL_AUTH_SANITIZE_REDIRECTS = False` : The auth process finishes with a redirect, by default it’s done to the value of `SOCIAL_AUTH_LOGIN_REDIRECT_URL` but can be overridden with `next` GET argument. If this setting is `True`, this application will vary the domain of the final URL and only redirect to it if it’s on the same domain. `SOCIAL_AUTH_ALLOWED_REDIRECT_HOSTS = ['foo', 'bar']` : To allow redirection to certain domains while keeping the more restrictive `SOCIAL_AUTH_SANITIZE_REDIRECTS = True` setting. This will redirect to the `next` GET argument if the hostname is on the list, otherwise it defaults to the value of `SOCIAL_AUTH_LOGIN_REDIRECT_URL`. `SOCIAL_AUTH_REDIRECT_IS_HTTPS = False` : On projects behind a reverse proxy that uses HTTPS, the redirect URIs can have the wrong schema (`http://` instead of `https://`) if the request lacks the appropriate headers, which might cause errors during the auth process. To force HTTPS in the final URIs set this setting to `True` `SOCIAL_AUTH_REQUESTS_TIMEOUT = 10` : Any `requests.request` call will be performed with the default timeout value, to change it without affecting the global socket timeout define this setting (the value specifies timeout seconds). `SOCIAL_AUTH_URLOPEN_TIMEOUT` : Deprecated: this was the old timeout setting before the move to `requests` If it’s defined, it will be used as the fallback for the above setting. If the above setting is defined, this one will be ignored. `SOCIAL_AUTH_VERIFY_SSL` : If set, it will be passed as the `verify` parameter to `requests.request` calls. To learn more, check the [Requests’ SSL verification page](https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification). `SOCIAL_AUTH_PROXIES` : If set, it will be passed as the `proxies` parameter to `requests.request` calls. To learn more, check the [Requests’ Proxies page](https://requests.readthedocs.io/en/latest/user/advanced/#proxies). ## Whitelists Registration can be limited to a set of users identified by their email address or domain name. To white-list just set any of these settings: `SOCIAL_AUTH__WHITELISTED_DOMAINS = ['foo.com', 'bar.com']` : Supply a list of domain names to be white-listed. Any user with an email address on any of the allowed domains will login successfully, otherwise `AuthPolicyError` is raised. `SOCIAL_AUTH__WHITELISTED_EMAILS = ['me@foo.com', 'you@bar.com']` : Supply a list of email addresses to be white-listed. Any user with an email address in this list will login successfully, otherwise `AuthPolicyError` is raised. ## Miscellaneous settings `SOCIAL_AUTH_FIRSTLAST_FROM_FULL = True` : Let the `social_names` pipeline step split `fullname` when neither `first_name` nor `last_name` is supplied. Set to `False` to disable this conversion. Supports backend-specific overrides, such as `SOCIAL_AUTH_SAML_FIRSTLAST_FROM_FULL`. See [Name normalization](pipeline.html.md#name-normalization). `SOCIAL_AUTH_FULL_FROM_FIRSTLAST = True` : Let the `social_names` pipeline step generate a missing `fullname` from `first_name` and/or `last_name`. Set to `False` to disable this conversion. Supports backend-specific overrides, such as `SOCIAL_AUTH_SAML_FULL_FROM_FIRSTLAST`. See [Name normalization](pipeline.html.md#name-normalization). `SOCIAL_AUTH_PROTECTED_USER_FIELDS = ['email',]` : During the pipeline process a `dict` named `details` will be populated with the needed values to create the user instance, but it’s also used to update the user instance. Any value in it will be checked as an attribute in the user instance (first by doing `hasattr(user, name)`). Usually there are attributes that cannot be updated (like `username`, `id`, `email`, etc.), those fields need to be *protect*. Set any field name that requires *protection* in this setting, and it won’t be updated. `SOCIAL_AUTH_IMMUTABLE_USER_FIELDS = ['email',]` : Set any field name that requires *protection* in this setting, and it won’t be updated after initial population. This setting is similar to `SOCIAL_AUTH_PROTECTED_USER_FIELDS` in that they both do not allow changes of the data - however this one allows it to be set if no prior value exists. An example use case might be an application that seeds data from a social platform but allows the users to override it locally. `SOCIAL_AUTH_SESSION_EXPIRATION = False` : By default, user session expiration time will be set by your web framework (in Django, for example, it is set with [SESSION_COOKIE_AGE](https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-SESSION_COOKIE_AGE)). Some providers return the time that the access token will live, which is stored in `UserSocialAuth.extra_data` under the key `expires`. Changing this setting to True will override your web framework’s session length setting and set user session lengths to match the `expires` value from the auth provider. `SOCIAL_AUTH_OPENID_PAPE_MAX_AUTH_AGE = ` : Enable [OpenID PAPE](http://openid.net/specs/openid-provider-authentication-policy-extension-1_0.html) extension support by defining this setting. `SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['foo',]` : If you want to store extra parameters from POST or GET in session, like it was made for `next` parameter, define this setting with the parameter names.
    In this case `foo` field’s value will be stored when user follows this link `...`. `SOCIAL_AUTH_PASSWORDLESS = False` : When this setting is `True` and `social_core.pipeline.mail.send_validation` is enabled, it allows the implementation of a [passwordless authentication mechanism](https://medium.com/@ninjudd/passwords-are-obsolete-9ed56d483eb). Example of this implementation can be found at [psa-passwordless](https://github.com/omab/psa-passwordless). `SOCIAL_AUTH_USER_AGENT = None` : Define the User-Agent header value sent to on every request done to the service provider, used when combined with a backend that sets the SEND_USER_AGENT property to True. Default value is the string social-auth-. `SOCIAL_AUTH_FORCE_EMAIL_LOWERCASE = False` : When this setting is `True` it is enabled. Once enabled, it will force all emails to be lowercase if they are provided using the email property by the backend. Default value is false. ## Account disconnection Disconnect is an side-effect operation and should be done by POST method only, some CSRF protection is encouraged (and enforced on Django app). Ensure that any call to /disconnect// or /disconnect/// is done using POST. `SOCIAL_AUTH_REVOKE_TOKENS_ON_DISCONNECT = False` : When disconnecting an account, it is recommended to trigger a token revoke action in the authentication provider, that way we inform it that the token won’t be used anymore and can be disposed. By default the action is not triggered because it’s not a common option on every provider, and tokens should be disposed automatically after a short time. # configuration/webpy.html.md # Webpy Framework [Webpy](http://webpy.org/) framework is easy to setup, once that [python-social-auth](https://github.com/python-social-auth) is installed or accessible in the `PYTHONPATH`, just add the needed configurations to make it run. ## Dependencies The Webpy app depends on [sqlalchemy](http://www.sqlalchemy.org/), there’s no support for others ORMs yet but pull-requests are welcome. ## Installing From [pypi](http://pypi.python.org/pypi/social-auth-app-webpy/): ```default $ pip install social-auth-app-webpy ``` ## Configuration Add the needed settings into `web.config` store. Settings are prefixed with `SOCIAL_AUTH_` but there’s a helper for it: ```default from social_core.utils import setting_name web.config[setting_name('USER_MODEL')] = 'models.User' web.config[setting_name('LOGIN_REDIRECT_URL')] = '/done/' web.config[setting_name('AUTHENTICATION_BACKENDS')] = ( 'social_core.backends.google.GoogleOAuth2', ... ) ``` Add all the settings needed for the app (check [Configuration]() section for details). ## URLs Add the social application into URLs: ```default from social_webpy import app as social_app urls = ( ... '', social_app.app_social ... ) ``` ## Session [python-social-auth](https://github.com/python-social-auth) depends on sessions storage to keep some essential values, usually redirects and `state` parameters used to validate authentication process on OAuth providers. The Webpy built-in app expects the session reference to be available under `web.web_session` so ensure it’s available there. ## User model Like the other apps, the User model must be defined on settings since a reference to it is kept on `UserSocialAuth` instance. Define like this: ```default web.config[setting_name('USER_MODEL')] = 'models.User' ``` Where the value is the import path to the User model used on your project. # copyright.html.md # Copyrights and Licence `python-social-auth` is protected by BSD licence. Check the [LICENCE](https://github.com/python-social-auth/social-core/blob/master/LICENSE) for details. The base work was derived from [django-social-auth](https://github.com/omab/django-social-auth) work and copyrighted too, check [django-social-auth LICENCE](https://github.com/omab/django-social-auth/blob/master/LICENSE) for details: # developer_intro.html.md # Beginner’s Guide This is an attempt to bring together a number of concepts in python-social-auth (PSA) so that you will understand how it fits into your system. This definitely has a Django flavor to it (because that’s how I learned it). ## Understanding PSA URLs If you have not seen namespaced URLs before, you are about to be introduced. When you add the PSA entry to your `urls.py`, it looks like this: ```default path("", include('social_django.urls', namespace="social")), ``` that “namespace” part on the end is what keeps the names in the PSA-world from colliding with the names in your app, or other 3rd-party apps. So your login form will look like this: ```default
    {% csrf_token %}
    ``` (See how “social” in the URL mapping matches the value of “namespace” in the `urls.py` entry?) #### SEE ALSO [URLs entries](configuration/django.html.md#django-urls) ## Understanding Backends PSA implements a lot of backends. Find the entry in the docs for your backend, and if it’s there, follow the steps to enable it, which come down to 1. Set up SOCIAL_AUTH_{backend} variables in settings.py. (The settings vary, based on the backends) 2. Adding your backend to AUTHENTICATION_BACKENDS in `settings.py`. If you need to implement a different backend (for instance, let’s say you want to use Intuit’s OpenID), you can subclass the nearest one and override the “name” attribute: ```default from social_core.backends.open_id import OpenIDAuth class IntuitOpenID(OpenIDAuth): name = 'intuit' ``` And then add your new backend to AUTHENTICATION_BACKENDS in settings.py. A couple notes about the pipeline: The standard pipeline does not log the user in until after the pipeline has completed. So if you get a value in the user key of the accumulative dictionary, that implies that the user was logged in when the process started. ## Understanding the Pipeline Reversing a URL like `{% url 'social:begin' 'github' %}` will give you a url like: ```default http://example.com/login/github ``` Submitting the login form to that URL will cause the “pipeline” to be started. The pipeline is a list of functions that build up data about the user as we go through the steps of the authentication process. (If you really want to understand the pipeline, look at the source in `social_core/backends/base.py`, and see the `run_pipeline()` function in `BaseAuth`.) The design contract for each function in the pipeline is: 1. The pipeline starts with an accumulative dictionary, which is updated with the results of each function in the pipeline. Common initial values include: `strategy` : contains a strategy object `backend` : contains the backend being used during this pipeline run `details` : which is an empty dict. Read effective request parameters through `strategy.request_data()`. In Django, `strategy.request` holds the native `HttpRequest`. Neither is automatically passed as a pipeline `request` argument. 2. If the function returns a dictionary or something False-ish, add the contents of the dictionary to an accumulative dictionary (called `out` in `run_pipeline`), and call the next step in the pipeline with the accumulative dictionary. 3. If something else is returned (for example, a subclass of `HttpResponse`), then return that to the browser. 4. If the pipeline completes, *THEN* the user is authenticated (logged in). So if you are finding an authenticated user object while the pipeline is running, that means that the user was logged in when the pipeline started. There is one pipeline for your site as a whole – if you have backend-specific logic, you have to make your pipeline steps smart enough to skip the step if it is not relevant. This is as simple as: ```default def my_custom_step(strategy, backend, details, *args, **kwargs): if backend.name != 'my_custom_backend': return parameters = strategy.request_data() # Perform the special steps for your custom backend using parameters. ``` ## Interrupting the Pipeline (and communicating with views) Let’s say you want to add a custom step in the pipeline – you want the user to establish a password so that they can come directly to your site in the future. We can do that with the @partial decorator, which tells the pipeline to keep track of where it is so that it can be restarted. The first thing we need to do is set up a way for our views to communicate with the pipeline. That is done by adding a value to the settings file to tell us which values should be passed back and forth between the session and the pipeline: ```default SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['local_password',] ``` In our pipeline code, we would have: ```default from django.shortcuts import redirect from django.contrib.auth.models import User from social_core.pipeline.partial import partial # partial says "we may interrupt, but we will come back here again" @partial def collect_password(strategy, backend, details, *args, **kwargs): # session 'local_password' is set by the pipeline infrastructure # because it exists in FIELDS_STORED_IN_SESSION local_password = strategy.session_get('local_password', None) if not local_password: # if we return something besides a dict or None, then that is # returned to the user -- in this case we will redirect to a # view that can be used to get a password return redirect("myapp.views.collect_password") # grab the user object from the database (remember that they may # not be logged in yet) and set their password. (Assumes that the # email address was captured in an earlier step.) user = User.objects.get(email=kwargs['email']) user.set_password(local_password) user.save() # continue the pipeline return ``` In our view code, we would have something like: ```default class PasswordForm(forms.Form): secret_word = forms.CharField(max_length=10) def get_user_password(request): if request.method == 'POST': form = PasswordForm(request.POST) if form.is_valid(): # because of FIELDS_STORED_IN_SESSION, this will get copied # to the pipeline's session state when it is resumed request.session['local_password'] = form.cleaned_data['secret_word'] # once we have the password stashed in the session, we can # tell the pipeline to resume by using the "complete" endpoint return redirect(reverse('social:complete', args=("backend_name,"))) else: form = PasswordForm() return render(request, "password_form.html") ``` Note that the `social:complete` will re-enter the pipeline with the same function that interrupted it (in this case, collect_password). # exceptions.html.md # Exceptions Social Auth exposes structured exceptions so applications can choose recovery without matching provider descriptions or exception messages. Catch `SocialAuthBaseException` for all Social Auth failures, including configuration errors. Catch `AuthException` for authentication-flow failures. Both retain their existing inheritance, including `ValueError`. Configuration errors inherit directly from `SocialAuthBaseException`. ## Exception families `AuthConfigurationError` : Missing or invalid settings, unavailable backends, or unsupported features. `AuthInputError` : Missing or invalid request or application input. `AuthSessionError` : Missing authentication context, state mismatch, or a different initiating user. `AuthResponseError` : Malformed provider responses or failed signature, claim, nonce, or expiry validation. `AuthCredentialError` : Rejected credentials, rejected authorization codes, revoked tokens, or required reauthentication. `AuthPolicyError` : Application authentication, membership, or disconnect policy rejection. `AuthAssociationError` : Local account conflicts or unsafe identifier migration. `AuthProviderError` : Connection, timeout, TLS, rate-limit, availability, or HTTP failures. `AuthCanceled` : Explicit authorization cancellation or refusal. `AuthUnknownError` : Authentication failures without a known classification. ## Structured attributes Each exception exposes `code`, `source`, `stage`, and `recovery`. Codes are stable machine-readable strings; messages and diagnostic descriptions are not part of the classification contract. `source` identifies the failing boundary, not who is responsible: `configuration`, `request`, `session`, `provider_response`, `local_policy`, `storage`, or `unknown`. `stage` identifies the operation: `begin`, `callback`, `token_exchange`, `token_validation`, `user_info`, `pipeline`, `refresh`, `disconnect`, or `unknown`. Custom integrations should supply the stage at the raise site. `recovery` suggests an action: `none`, `correct_input`, `restart_login`, `reauthenticate`, `retry_later`, `check_provider_profile`, `use_existing_account`, or `contact_administrator`. These hints do not perform retries or redirects and do not determine whether to report a failure. Optional attributes are `backend`, `parameter`, `claim`, `provider_code`, `status_code`, and `retry_after`. `retry_after` preserves the provider’s HTTP header; applications must interpret it before using it. `str(exception)` and `exception.args` contain a safe default message. Provider descriptions are available separately in `detail`. `context` is an explicitly supplied mapping for diagnostic identifiers, such as user ID and provider UID. Original exceptions remain available through exception chaining. Do not send diagnostics, raw responses, or identifying context to client URLs or flash messages. Do not log tokens, cookies, or full authentication assertions. `public_metadata()` returns only `error_code`, `error_source`, `error_stage`, and `error_recovery`. ```python from social_core.exceptions import AuthResponseError, AuthException if "sub" not in claims: raise AuthResponseError( backend, code="missing_claim", claim="sub", stage="token_validation" ) try: authenticate() except AuthException as error: if error.code == "response_expired": show_restart_login_message() else: show_generic_authentication_message() ``` Application-specific codes should have a namespace, for example `myapp.registration_disabled`. Explicitly set their source and recovery. Unknown codes use the family’s safe default message and metadata. Never derive a code from a free-form message. ## Reason codes Defaults are listed below. A raise site can override source or recovery when its operation supplies more precise information. | Code | Source | Suggested recovery | |---------------------------------|---------------------|--------------------------| | `missing_setting` | `configuration` | `contact_administrator` | | `invalid_setting` | `configuration` | `contact_administrator` | | `unsupported_feature` | `configuration` | `contact_administrator` | | `backend_missing` | `configuration` | `contact_administrator` | | `missing_parameter` | `request` | `correct_input` | | `invalid_parameter` | `request` | `correct_input` | | `session_context_missing` | `session` | `restart_login` | | `state_mismatch` | `session` | `restart_login` | | `user_mismatch` | `session` | `restart_login` | | `malformed_response` | `provider_response` | `contact_administrator` | | `missing_claim` | `provider_response` | `contact_administrator` | | `invalid_claim` | `provider_response` | `contact_administrator` | | `invalid_signature` | `provider_response` | `contact_administrator` | | `nonce_mismatch` | `provider_response` | `restart_login` | | `response_expired` | `provider_response` | `restart_login` | | `response_not_yet_valid` | `provider_response` | `contact_administrator` | | `invalid_expiry` | `storage` | `contact_administrator` | | `profile_email_missing` | `provider_response` | `check_provider_profile` | | `authorization_code_rejected` | `provider_response` | `restart_login` | | `credential_rejected` | `provider_response` | `reauthenticate` | | `token_revoked` | `provider_response` | `reauthenticate` | | `reauthentication_required` | `storage` | `reauthenticate` | | `email_verification_rejected` | `request` | `restart_login` | | `authentication_disallowed` | `local_policy` | `contact_administrator` | | `membership_required` | `local_policy` | `contact_administrator` | | `disconnect_disallowed` | `local_policy` | `none` | | `identity_in_use` | `storage` | `use_existing_account` | | `email_in_use` | `storage` | `use_existing_account` | | `username_in_use` | `storage` | `use_existing_account` | | `identifier_migration_conflict` | `storage` | `contact_administrator` | | `connection_failed` | `provider_response` | `retry_later` | | `timeout` | `provider_response` | `retry_later` | | `tls_error` | `provider_response` | `contact_administrator` | | `rate_limited` | `provider_response` | `retry_later` | | `unavailable` | `provider_response` | `retry_later` | | `http_error` | `provider_response` | `contact_administrator` | | `authorization_declined` | `provider_response` | `none` | | `unknown_error` | `unknown` | `contact_administrator` | ## Provider failures HTTP status alone does not establish cancellation, expired credentials, or a local policy rejection. Shared HTTP handling retains status and structured provider codes. Unknown provider codes remain provider errors. For OAuth, `invalid_client` is a configuration failure and `invalid_grant` is credential rejection. The latter does not establish expiry. Explicit `access_denied` indicates authorization refusal. HTTP 429 and server errors receive retry-later guidance; TLS verification failures require administrator attention without suggesting that verification be disabled. ## Token renewal failures A stored account with a known expired access token and no usable renewal credential raises `AuthCredentialError` with `code='reauthentication_required'`, `source='storage'`, `stage='refresh'`, and `recovery='reauthenticate'`. This applies to explicit `refresh_token()` and automatic renewal through `get_access_token()`. No token request is sent, and stored credentials remain unchanged. Applications should arrange another provider login when handling this error. See [Token renewal](backends/oauth.html.md#oauth-token-renewal) for valid tokens, unknown expiry, and backend-specific renewal credentials. ## Migration from legacy exceptions This is a breaking change. `SocialAuthBaseException` and `AuthException` remain available for broad catches. `AuthCanceled` and `AuthUnknownError` also remain available, so catches of these types can be retained. Removed names have no aliases or wrappers. Update custom backends, pipelines, and catches of removed types together with the library upgrade. | Previous exception | Replacement | |---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| | `AuthFailed` / `AuthTokenError` | Choose response, credential, session, policy, or provider failure from the actual cause. | | `AuthMissingParameter` / `AuthInvalidParameter` | Input errors for request data; configuration errors for settings; response errors for provider fields. | | `AuthStateMissing` / `AuthStateForbidden` | Session errors with `session_context_missing` / `state_mismatch`. | | `AuthUserMismatch` | `AuthSessionError` with `user_mismatch`. | | `AuthTooManyRequests` | `AuthProviderError` with `rate_limited`. | | `AuthForbidden` | Local policy errors; session errors for user mismatch; provider errors for HTTP rejection. | | `AuthAlreadyAssociated` | Association errors with an explicit identity, username, email, or migration-conflict code. | | `AuthTokenRevoked` / `AuthReauthenticationRequired` | Credential errors with `token_revoked` / `reauthentication_required`. | | `AuthConnectionError` / `AuthUnreachableProvider` | Provider errors distinguishing connection, timeout, TLS, rate limit, and availability. | | `InvalidEmail` | Credential error with `email_verification_rejected`. | | `NotAllowedToDisconnect` | Policy error with `disconnect_disallowed`. | | `InvalidExpiryValue` | Response error with `invalid_expiry`, source `storage`, and `parameter` identifying the field. | | `WrongBackend` / `MissingBackend` | Configuration error with `backend_missing`. | | Strategy/configuration errors / `AuthNotImplementedParameter` | Configuration errors with missing/invalid settings or `unsupported_feature`. | Previously, `AuthStateMissing` meant missing session state, while missing callback state raised `AuthMissingParameter`. Preserve that distinction when migrating: use a session error for missing saved state and an input error for a missing callback parameter. Construct failures with a backend (or `None` where unavailable) and keyword metadata. Keep provider descriptions in diagnostic positional arguments. For example, replace `AuthTokenError(backend, "Signature has expired")` at a confirmed expiry boundary with: ```default AuthResponseError( backend, "Signature has expired", code="response_expired", stage="token_validation", ) ``` Do not translate that text into a code elsewhere in the application. # groups.html.md # External groups External memberships can restrict authentication and synchronize local groups. Both capabilities are opt-in. Extraction does not grant local permissions. ## Enable extraction For OpenID Connect, Keycloak, and Okta, select a literal claim name: ```default SOCIAL_AUTH_OIDC_GROUPS_KEY = 'groups' SOCIAL_AUTH_KEYCLOAK_GROUPS_KEY = 'groups' SOCIAL_AUTH_OKTA_OAUTH2_GROUPS_KEY = 'groups' SOCIAL_AUTH_OKTA_OPENIDCONNECT_GROUPS_KEY = 'groups' ``` Okta OAuth2 reads UserInfo; Okta OpenID Connect uses the validated ID token first, then UserInfo with a matching subject. Configure Okta to issue the claim. Org authorization servers require the `groups` scope; custom authorization servers require any scope associated with the claim, if any. See [Okta](backends/okta.html.md) for backend-specific scopes and a Django synchronization example. For Azure, use the setting corresponding to the selected authentication backend: #### Azure group extraction settings | Backend class | Setting | |-------------------------|---------------------------------------------------| | `AzureADOAuth2` | `SOCIAL_AUTH_AZUREAD_OAUTH2_GROUPS_KEY` | | `AzureADOAuth2V2` | `SOCIAL_AUTH_AZUREAD_OAUTH2_V2_GROUPS_KEY` | | `AzureADTenantOAuth2` | `SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_KEY` | | `AzureADV2TenantOAuth2` | `SOCIAL_AUTH_AZUREAD_V2_TENANT_OAUTH2_GROUPS_KEY` | | `AzureADB2COAuth2` | `SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_GROUPS_KEY` | Set the selected Azure setting to `'roles'` for Microsoft Entra application roles, or `'groups'` for group identifiers. Configure the provider to issue the selected claim. OIDC uses the validated ID token first, then UserInfo with a matching subject. Claim names are literal keys; nested claim paths are not supported. GitLab, MediaWiki, and Discourse use `GROUPS_ENABLED` instead: ```default SOCIAL_AUTH_GITLAB_GROUPS_ENABLED = True SOCIAL_AUTH_GITLAB_GROUPS_IDENTIFIER = 'full_path' ``` With `GROUPS_ENABLED = True`, GitLab requests `read_api` automatically unless `read_api` or `api` is already included in the requested scopes. Enable the matching permission in the GitLab OAuth application’s settings; `read_user` alone cannot retrieve groups. GitLab returns full group paths by default. Set `GROUPS_IDENTIFIER = 'id'` for stable numeric IDs, represented as strings. Paths are readable but renames, moves, and reuse can change authorization. Memberships are fetched from every page on the configured `API_URL`; visible groups without membership do not qualify. Insufficient scope or a failed page aborts authentication. For SAML, configure each identity provider independently: ```default SOCIAL_AUTH_SAML_ENABLED_IDPS = { 'company': { # Existing IdP configuration goes here. 'attr_groups': 'https://example.com/claims/groups', 'allow_groups': ['translators', 'reviewers'], 'groups_map': {'translators': ['Translators']}, }, } ``` The complete SAML attribute is read; a singleton string is accepted. ## Missing and empty memberships `get_user_groups(response)` returns a list of exact, nonempty string identifiers, with duplicates removed. `None` means extraction is disabled; `[]` means the provider reported no memberships. A missing configured claim fails authentication by default. Providers that omit the claim for users without assignments can explicitly enable: ```default SOCIAL_AUTH_OIDC_GROUPS_MISSING_AS_EMPTY = True ``` SAML uses `groups_missing_as_empty` inside the IdP configuration. Malformed claims always fail. Entra group overage also fails when reading groups, even with this option enabled. There is no Microsoft Graph fallback; prefer application roles or configure application-scoped groups. Only trust group claims from the intended issuer and tenant. In particular, restrict Azure’s common endpoint appropriately before granting local access. ## Restrict authentication The existing `auth_allowed` pipeline step enforces `ALLOW_GROUPS`: ```default SOCIAL_AUTH_OIDC_ALLOW_GROUPS = ['translators', 'reviewers'] ``` Membership in any listed group qualifies. Email/domain restrictions still apply. An empty allow list imposes no group restriction. A nonempty allow list requires enabled extraction. SAML uses per-IdP `allow_groups`. Existing `SOCIAL_AUTH_CAS_ALLOW_GROUPS` settings keep their behavior without new extraction settings or pipeline steps. CAS reads `groups` when a nonempty allow list or group mapping is configured, or when `SOCIAL_AUTH_CAS_GROUPS_ENABLED = True` explicitly enables extraction for a custom pipeline. With group handling disabled, CAS ignores the group attribute and returns `None`. When enabled, CAS validates the membership list and continues to treat a missing claim as empty membership. ## Synchronize Django groups Map external identifiers to lists of existing Django group names: ```default SOCIAL_AUTH_OIDC_GROUPS_MAP = { 'translators': ['Translators'], 'reviewers': ['Reviewers', 'Translators'], } ``` Append `social_core.pipeline.user.sync_groups` after user creation and all application authentication checks in `SOCIAL_AUTH_PIPELINE`. Keep the existing `social_details` and `auth_allowed` steps; no extra extraction or restriction steps are required. For example, extend the standard pipeline: ```default from social_core.pipeline import DEFAULT_AUTH_PIPELINE SOCIAL_AUTH_PIPELINE = ( *DEFAULT_AUTH_PIPELINE, 'social_core.pipeline.user.sync_groups', ) ``` The mapping targets define the memberships managed by this provider. Desired memberships are added and obsolete managed memberships removed atomically. Other groups are preserved. Manual membership in managed groups is replaced at the next authentication. Empty memberships remove all managed memberships. Django synchronization uses a transaction so a failed membership update rolls back the changes. It does not lock user or group rows. Concurrent authentications with different membership snapshots can interleave and leave a combination of their memberships. Applications requiring serialized synchronization should override `strategy.sync_user_groups` and coordinate membership updates using their own locking policy. Synchronization does not prevent administrators from renaming or deleting mapped groups concurrently. An empty mapping disables synchronization. Unknown external groups grant nothing; use `ALLOW_GROUPS` to restrict login independently. Missing local groups, invalid configuration, disabled extraction with an enabled mapping, and competing provider/IdP ownership of a local group cause errors before membership changes. No groups are created and staff/superuser flags are not modified. The default Django implementation requires `auth.Group` and an automatically created membership table. Custom group models and explicit intermediary models must override `strategy.sync_user_groups` to supply their application-specific membership behavior. These unsupported relations are rejected before any membership changes when synchronization is configured. Synchronization runs during authentication, including registration and linking. It does not provide background revocation, account deactivation, or SCIM provisioning. Association-only backends do not synchronize memberships. ## Custom strategies and pipelines `social_details` exposes memberships as the top-level pipeline argument `groups`, separate from profile `details`. Partial pipelines preserve this argument. There is no automatic external-group snapshot in association `extra_data`. Override `strategy.sync_user_groups(user, groups, *, backend, response, **kwargs)` for application-specific behavior. `DjangoStrategy` supplies the standard Django implementation. `BaseStrategy` rejects configured synchronization without an implementation. Application strategies should validate all targets before changing memberships and retain their own audit, transaction, and permission-cache behavior. `social_core.groups.group_sync_targets(backend, groups, response)` returns the desired and managed sets of local target identifiers, validating mapping syntax and ownership across configured providers. SAML resolves its mapping from `response['idp_name']`. Strategies interpret local target identifiers; for example, Weblate uses team IDs instead of Django group names. MediaWiki and Discourse no longer return groups inside `details`. Existing custom consumers should enable extraction and use the `groups` pipeline argument. This prevents profile updates from assigning a many-to-many field. # installing.html.md # Installation [python-social-auth](https://github.com/python-social-auth) is a very modular library looking to provide the basic tools to implement social authentication / authorization in Python projects. For that reason, the project is split in smaller components that focus on providing a simpler functionality. Some components are: * [social-auth-core](https://github.com/python-social-auth/social-core) Core library that the rest depends on, this contains the basic functionality to establish an authentication/authorization flow with the different supported providers. * [social-auth-storage-sqlalchemy](https://github.com/python-social-auth/social-storage-sqlalchemy), [social-auth-storage-peewee](https://github.com/python-social-auth/social-storage-peewee), [social-auth-storage-mongoengine](https://github.com/python-social-auth/social-storage-mongoengine) Different storage solutions that can be reused across the supported frameworks or newer implementations. * [social-auth-app-django](https://github.com/python-social-auth/social-app-django), [social-auth-app-django-mongoengine](https://github.com/python-social-auth/social-app-django-mongoengine) Django framework integration * [social-auth-app-flask](https://github.com/python-social-auth/social-app-flask), [social-auth-app-flask-sqlalchemy](https://github.com/python-social-auth/social-app-flask-sqlalchemy), [social-auth-app-flask-mongoengine](https://github.com/python-social-auth/social-app-flask-mongoengine), [social-auth-app-flask-peewee](https://github.com/python-social-auth/social-app-flask-peewee) Flask framework integration * [social-auth-app-pyramid](https://github.com/python-social-auth/social-app-pyramid) Pyramid framework integration * [social-auth-app-cherrypy](https://github.com/python-social-auth/social-app-cherrypy) Cherrypy framework integration * [social-auth-app-tornado](https://github.com/python-social-auth/social-app-tornado) Tornado framework integration * [social-auth-app-webpy](https://github.com/python-social-auth/social-app-webpy) Webpy framework integration ## Dependencies Dependencies are properly defined in the requirements files. There are some `extras` defined to install the corresponding dependencies since they are required to build extensions that, unless used, are undesired. * [SAML](backends/saml.html.md) support requires the use of the `saml` extra. * [Shopify](backends/shopify.html.md) support requires the use of the `shopify` extra. * [Google](backends/google.html.md) One Tap support requires the use of the `google-onetap` extra. * [Microsoft Entra ID and Azure AD B2C](backends/azuread.html.md) support requires the use of the `azuread` extra. There’s also the `all` extra that will install all the extra options. Several backends demand application registration on their corresponding sites and other dependencies like [SQLAlchemy](http://www.sqlalchemy.org/) on Flask and Webpy. ## Get a copy From [PyPI](https://pypi.org/project/social-auth-core/): ```default $ pip install social-auth- ``` Or, grab the relevant repository from [GitHub](https://github.com/python-social-auth/), then: ```default $ cd social-auth- $ sudo python setup.py install ``` ## Using the `extras` options To enable any of the `extras` options to bring the dependencies for [SAML](https://www.onelogin.com/saml), or all: ```default $ pip install "social-auth-core[saml]" $ pip install "social-auth-core[all]" ``` # intro.html.md # Introduction Python Social Auth aims to be an easy to setup social authentication and authorization mechanism for Python projects supporting protocols like [OAuth](http://oauth.net/) (1 and 2), [OpenID](http://openid.net/) and others. ## Features This application provides user registration and login using social sites credentials, here are some features, probably not a full list yet. ### Supported frameworks Multiple frameworks support: * [Django](https://github.com/python-social-auth/social-app-django) * [Flask](https://github.com/python-social-auth/social-app-flask) * [Pyramid](http://www.pylonsproject.org/projects/pyramid/about) * [Webpy](https://github.com/python-social-auth/social-app-webpy) * [Tornado](http://www.tornadoweb.org/) More frameworks can be added easily (and should be even easier in the future once the code matures). ### Auth providers Several supported service by simple backends definition (easy to add new ones or extend current one): * [Angel](https://angel.co) OAuth2 * [Behance](https://www.behance.net) OAuth2 * [Bitbucket](https://bitbucket.org) OAuth1 * [Box](https://www.box.com) OAuth2 * [Dailymotion](https://dailymotion.com) OAuth2 * [Deezer](https://www.deezer.com) OAuth2 * [Disqus](https://disqus.com) OAuth2 * [Douban](http://www.douban.com) OAuth2 * [Dropbox](https://dropbox.com) OAuth2 * [Eventbrite](https://www.eventbrite.com) OAuth2 * [Evernote](https://www.evernote.com) OAuth1 * [Facebook](https://www.facebook.com) OAuth2 and OAuth2 for Applications * [Fitbit](https://fitbit.com) OAuth2 and OAuth1 * [Flat](https://flat.io) OAuth2 * [Flickr](http://www.flickr.com) OAuth1 * [Foursquare](https://foursquare.com) OAuth2 * [GitHub](https://github.com) OAuth2 * [Google](http://google.com) OAuth1 and OAuth2 * [Instagram](https://instagram.com) OAuth2 * [Kakao](https://kakao.com) OAuth2 * [Keycloak](https://www.keycloak.org) OpenID * [Linkedin](https://www.linkedin.com) OAuth1 * [Live](https://www.live.com) OAuth2 * [Livejournal](http://livejournal.com) OpenID * [Mailru](https://mail.ru) OAuth2 * [MineID](https://www.mineid.org) OAuth2 * [Mixcloud](https://www.mixcloud.com) OAuth2 * [NGPVAN ActionID](http://developers.ngpvan.com/action-id) OpenID * [Odnoklassniki](http://www.odnoklassniki.ru) OAuth2 and Application Auth * [OpenID](http://openid.net/) * [Podio](https://podio.com) OAuth2 * [Pinterest](https://www.pinterest.com) OAuth2 * [Shopify](http://shopify.com) OAuth2 * [Skyrock](https://skyrock.com) OAuth1 * [Soundcloud](https://soundcloud.com) OAuth2 * [Spotify](https://www.spotify.com) OAuth2 * [Stackoverflow](http://stackoverflow.com/) OAuth2 * [Steam](http://steamcommunity.com/) OpenID * [Stocktwits](https://stocktwits.com) OAuth2 * [Stripe](https://stripe.com) OAuth2 * [Tripit](https://www.tripit.com) OAuth1 * [Tumblr](http://www.tumblr.com/) OAuth1 * [Twilio](https://www.twilio.com) Connect association * [Twitch](http://www.twitch.tv/) OAuth2 * [Twitter](http://twitter.com) OAuth1 * [Upwork](https://www.upwork.com) OAuth1 * [Vimeo](https://vimeo.com/) OAuth1 * [VK.com](http://vk.com) OpenAPI, OAuth2 and OAuth2 for Applications * [Weibo](http://weibo.com) OAuth2 * [Xing](https://www.xing.com) OAuth1 * [Yahoo](http://yahoo.com) OAuth2 * [Yammer](https://www.yammer.com) OAuth2 * [Yandex](https://yandex.ru) OAuth1, OAuth2 and OpenID ### User data Basic user data population, to allow custom fields values from providers response. ### Social accounts association Multiple social accounts can be associated to a single user. ### Authentication and disconnection processing Extensible pipeline to handle authentication, association and disconnection mechanism in ways that suits your project. Check [Authentication Pipeline](pipeline.html) section. # logging_out.html.md # Disconnect and Logging Out It’s a common misconception that the `disconnect` action is the same as logging the user out, but this is not the case. `Disconnect` is the way that your users can ask your project to “forget about my account”. This implies removing the `UserSocialAuth` instance that was created, this also implies that the user won’t be able to login back into your site with the social account. Instead the action will be a signup, a new user instance will be created, not related to the previous one. Logging out is just a way to say “forget my current session”, and usually implies removing cookies, invalidating a session hash, etc. The many frameworks have their own ways to logout an account (Django has `django.contrib.auth.logout`), `flask-login` has it’s own way too with [logout_user()](https://github.com/maxcountryman/flask-login/blob/a96de342eae560deec008a02179f593c3799b3ba/flask_login.py#L718-L739). Some providers also maintain their own sign-in session. Clear the local session and redirect the browser to the provider’s logout endpoint when provider logout is required. Azure AD B2C provides a URL helper and a Django example; see [B2C provider logout](backends/azuread.html.md#azure-b2c-logout). Provider logout does not remove the social account association. Since disconnecting a social account means that the user won’t be able to log back in with that social provider into the same user, python-social-auth will check that the user account is in a valid state for disconnection (it has at least one more social account associated, or a password, etc). This behavior can be overridden by changing the [Disconnection Pipeline](pipeline.html#disconnection-pipeline). # maintainers.html.md # Maintainers This project is maintained by: * [Matías Aguirre](https://github.com/omab) * [Michal Čihař](https://github.com/nijel) The project is open for mainteners, take a look to [issue #539](https://github.com/python-social-auth/social-core/issues/539) for details. # pipeline.html.md # Pipeline [python-social-auth](https://github.com/python-social-auth) uses an extendible pipeline mechanism where developers can introduce their functions during the authentication, association and disconnection flows. ## Pipeline Overview The pipeline is a sequence of functions that are executed in order during the authentication process. Each function receives data from the previous steps and can pass data to the next steps. **Key Concepts:** * **Pipeline functions** are called sequentially in the order they are defined * **Each function** receives arguments from the authentication process and previous pipeline steps * **Functions can pass data forward** by returning a dictionary * **Functions can interrupt the flow** by returning an HTTP response (e.g., redirect) * **All functions should accept** `**kwargs` to handle unexpected arguments gracefully ### Understanding Return Values Pipeline functions can return three types of values, each with different behavior: 1. **Return** `None` **or nothing**: The pipeline continues to the next function. This is equivalent to returning an empty dict `{}`. 2. **Return a** `dict`: The values in the dictionary are merged into the `kwargs` for all subsequent pipeline functions. This is how you pass data forward in the pipeline. Example: ```default def my_pipeline_function(backend, user, **kwargs): # Calculate something custom_value = "some data" # Pass it to next functions return {'custom_value': custom_value} ``` 3. **Return any other value** (HTTP response, redirect, etc.): The pipeline is interrupted and the value is returned directly to the client. This is useful for partial pipelines where you need user input. Example: ```default def my_pipeline_function(backend, user, **kwargs): if some_condition: # Interrupt pipeline and redirect user return redirect('/some-form/') ``` ### Common Function Parameters The functions will receive a variable set of arguments related to the current process. Common arguments include: * `strategy` - The current strategy instance (provides access to storage, settings, and request) * `backend` - The current backend instance (the social authentication provider) * `user` - The user instance (`None` if not yet created or retrieved) * `social` - The `UserSocialAuth` instance (`None` until created) * `uid` - The unique user ID from the provider * `response` - The raw response from the authentication provider * `details` - Processed user details (username, email, etc.) * `groups` - Normalized external memberships, or `None` when extraction is disabled; see [External groups](groups.html.md) * `is_new` - Boolean indicating if a user was just created * Any values returned as dicts by previous pipeline functions Read effective request parameters through `strategy.request_data()`. The native framework request is available as `strategy.request` when the integration provides one. Neither is automatically passed as a pipeline `request` argument. **Important:** Always include `**kwargs` in your function signature to handle additional arguments that may be passed from other pipeline functions or future versions: ```default def my_custom_pipeline(strategy, backend, user, **kwargs): # Your code here pass ``` ## Authentication Pipeline The authentication workflow is handled by a pipeline where custom functions can be added or default items can be removed to provide custom behavior. The default pipeline creates user instances and gathers basic data from providers. ### Understanding the Default Pipeline The pipeline executes in order, with each step depending on data from previous steps. Here’s what happens at each stage: The default pipeline is composed by: ```default ( # Get the information we can about the user and return it in a simple # format to create the user instance later. In some cases the details are # already part of the auth response from the provider, but sometimes this # could hit a provider API. 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', # Get the social uid from whichever service we're authing thru. The uid is # the unique identifier of the given user in the provider. 'social_core.pipeline.social_auth.social_uid', # Verifies that the current auth process is valid within the current # project, this is where emails and domains whitelists are applied (if # defined). 'social_core.pipeline.social_auth.auth_allowed', # Checks if the current social-account is already associated in the site. 'social_core.pipeline.social_auth.social_user', # Make up a username for this person, appends a random string at the end if # there's any collision. 'social_core.pipeline.user.get_username', # Send a validation email to the user to verify its email address. # Disabled by default. # 'social_core.pipeline.mail.mail_validation', # Associates the current social details with another user account with # a similar email address. Disabled by default. # 'social_core.pipeline.social_auth.associate_by_email', # Create a user account if we haven't found one yet. 'social_core.pipeline.user.create_user', # Create the record that associates the social account with the user. 'social_core.pipeline.social_auth.associate_user', # Populate the extra_data field in the social record with the values # specified by settings (and the default ones like access_token, etc). 'social_core.pipeline.social_auth.load_extra_data', # Update the user record with any changed info from the auth service. 'social_core.pipeline.user.user_details', ) ``` ### Name normalization The default pipeline runs `social_core.pipeline.social_auth.social_names` after `social_details`. Backends return the names supplied by the provider; `social_names` fills missing representations in `details` before user creation, extra-data storage, and user updates. When both `first_name` and `last_name` are empty, a nonempty `fullname` is split at the first space. For example, `Mary Jane Watson` becomes `Mary` and `Jane Watson`. A single name becomes `first_name`, with an empty `last_name`. If either component is supplied, it is preserved and the other component is not inferred. A missing `fullname` is generated from either or both components. When `first_name` already appears as a complete name component or sequence of components in `last_name` (matched case-sensitively at whitespace boundaries), the full name uses `last_name` alone. For example, `Jane` and `Jane Watson` produce `Jane Watson`, while `Ann` and `Anniston` produce `Ann Anniston`. Otherwise, the components are joined with a space. Surrounding whitespace is removed. Supplied nonempty names take precedence, even when the representations differ. Missing or `None` names are preserved when no nonempty name is available. Set `SOCIAL_AUTH_FIRSTLAST_FROM_FULL` or `SOCIAL_AUTH_FULL_FROM_FIRSTLAST` to `False` to disable one direction. Both default to `True` and support backend-specific overrides, such as `SOCIAL_AUTH_SAML_FIRSTLAST_FROM_FULL = False`. These settings are read only by `social_names`. #### IMPORTANT Existing custom pipelines must add `social_core.pipeline.social_auth.social_names` after `social_details` to retain automatic name conversion. Built-in backends no longer perform this conversion in `get_user_details()`. Remove or replace `social_names` to customize normalization, including in backend-specific pipelines. `BaseAuth.get_user_names()` is deprecated and emits `DeprecationWarning`. Third-party backends should return provider-supplied names and let the pipeline normalize them. The compatibility helper still converts names before the pipeline, so the pipeline settings cannot undo conversion performed by callers of that helper. **What Data is Available When?** Understanding which data is available at each stage is crucial for placing your custom functions correctly: * **After** `social_details`: `details` dict is populated with user info * **After** `social_names`: missing name representations are populated * **After** `social_uid`: `uid` contains the provider’s user ID * **After** `social_user`: `social` may contain the UserSocialAuth instance (if user was previously authenticated) * **After** `get_username`: `username` is available * **After** `create_user`: `user` contains the User instance (new or existing) * **After** `associate_user`: `social` contains the UserSocialAuth instance * **After** `load_extra_data`: `social.extra_data` contains access tokens and additional provider data ### Customizing the Pipeline You can override the default pipeline by defining the setting `SOCIAL_AUTH_PIPELINE`. **Example 1: Preventing New User Creation** A pipeline that won’t create users, just accepts already registered ones would look like this: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` #### NOTE This example removes `get_username` and `create_user` steps, so only users who have previously authenticated can log in. **Example 2: Custom User Loading** When authentication is purely external, you need a custom pipeline function that populates the `user` key. This function should load or identify the user before the `social_user` step: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'myapp.pipeline.load_user', # Custom function to load the user 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` Your `load_user` function might look like: ```default def load_user(strategy, backend, uid, user=None, **kwargs): if user: return {'user': user} # Load user from your custom authentication system user = MyUserModel.get_by_external_id(uid) return {'user': user} ``` ### Per-Backend Pipelines It is also possible to define pipelines on a per backend basis by defining a setting such as `SOCIAL_AUTH_TWITTER_PIPELINE`. Backend-specific pipelines will override the default and `SOCIAL_AUTH_PIPELINE` settings. ## Disconnection Pipeline Like the authentication pipeline, it’s possible to define a disconnection pipeline if needed. For example, this can be useful on sites where a user that disconnects all the related social account is required to fill a password to ensure the authentication process in the future. This can be accomplished by overriding the default disconnection pipeline and setup a function that checks if the user has a password, in case it doesn’t a redirect to a fill-your-password form can be returned and later continue the disconnection process, take into account that disconnection ensures the POST method by default, a simple method to ensure this, is to make your form POST to `/disconnect/` and set the needed password in your pipeline function. Check *Partial Pipeline* below. In order to override the disconnection pipeline, just define the setting: ```default SOCIAL_AUTH_DISCONNECT_PIPELINE = ( # Verifies that the social association can be disconnected from the current # user (ensure that the user login mechanism is not compromised by this # disconnection). 'social_core.pipeline.disconnect.allowed_to_disconnect', # Collects the social associations to disconnect. 'social_core.pipeline.disconnect.get_entries', # Revoke any access_token when possible. 'social_core.pipeline.disconnect.revoke_tokens', # Removes the social associations. 'social_core.pipeline.disconnect.disconnect', ) ``` Backend specific disconnection pipelines can also be defined with a setting such as `SOCIAL_AUTH_TWITTER_DISCONNECT_PIPELINE`. ## Partial Pipeline The partial pipeline feature allows you to pause the authentication process to request additional information from the user, then resume where you left off. ### How Partial Pipelines Work 1. **Pause the pipeline**: Use the `@partial` decorator on your function 2. **Return an HTTP response**: Redirect the user to a form or page 3. **User completes the action**: User fills out a form and submits it 4. **Resume the pipeline**: User is redirected back to `/complete//` from the same browser session and the pipeline resumes from the same function ### Basic Example Here’s a simple example of collecting additional user information: ```default from social_core.pipeline.partial import partial @partial def require_email(strategy, backend, details, user=None, **kwargs): if user and user.email: # User already has email, continue return # Check if email was submitted in this request email = strategy.request_data().get('email') if email: # Email was provided, pass it forward return {'details': {'email': email}} # No email yet - interrupt pipeline and show form return strategy.render_html('email_form.html') ``` In your template, the form should POST to `/complete//`. **Django example**: ```default
    {% csrf_token %}
    ``` ### How Partial Data is Stored `@partial` stores the pipeline state in a database table named `social_auth_partial` and stores the current partial token in the browser session. By default, the stored pipeline can resume only from the browser session that created it. This prevents a `partial_token` copied into another browser from acting as a bearer login credential. The partial token is passed via the `partial_token` parameter (by default). The library automatically picks this value from the request, but it resumes the process only when the token belongs to the current session. ### Accessing Partial Data Pipeline functions receive a `current_partial` instance containing: * `current_partial.token` - The unique token for this partial process * `current_partial.backend` - The backend name * `current_partial.pipeline_type` - `authentication` or `disconnect`; the saved step can resume only in the matching pipeline * Other saved data from the pipeline Example of using the partial token in a redirect: ```default from urllib.parse import urlencode @partial def my_partial_function(strategy, backend, current_partial=None, **kwargs): # Check if user needs to provide additional information if not kwargs.get('phone_number'): # Include partial_token in the URL params = urlencode({'partial_token': current_partial.token}) url = f'/my-form/?{params}' return redirect(url) ``` ### Configuration To override the default parameter name: ```default SOCIAL_AUTH_PARTIAL_PIPELINE_TOKEN_NAME = 'my_token_name' ``` ### External resume links Some partial flows intentionally send the partial token out of band, for example by e-mail or SMS. Use `partial_step` with `allow_external_resume` only for those flows: ```default from social_core.pipeline.partial import partial_step @partial_step(save_to_session=True, allow_external_resume=True) def my_external_validation(strategy, backend, current_partial=None, **kwargs): ... ``` Externally resumed partials do not resume immediately when a request supplies the partial token, even in the browser session that created the partial. The first request stores pending resume state in the current browser session and asks the Strategy to render a local confirmation response. A later confirmation request from the same browser resumes the pipeline and replays the original link request data through `strategy.request_data()`. The confirmation request must include the parameter configured by `SOCIAL_AUTH_PARTIAL_PIPELINE_EXTERNAL_RESUME_CONFIRMATION_PARAMETER`. The default parameter name is `partial_pipeline_confirm`. A hidden field such as `partial_pipeline_confirm=1` is enough for core to select the pending external resume; your Strategy should still verify any local confirmation state it created, such as a nonce stored in the browser session. If your pipeline step needs the original link parameters after confirmation, read them like this: ```default data = strategy.request_data() ``` Confirmation state is checked against the current framework request before replay is activated. Effective data combines the saved link parameters with the confirmation request’s parameters, with current values taking precedence when a key appears in both. Ordinary session-owned partial resumes use current request parameters, so newly submitted form values remain available. For Django, `social-auth-app-django` provides the default confirmation page. Override the `social_django/partial_pipeline_external_resume.html` template to customize it. The confirmation form must require an explicit user action and must not send `partial_token` or validation codes again. Custom templates must still include the confirmation parameter described above. They must also include the nonce field from the template context, using `confirmation_nonce_parameter` as the field name and `confirmation_nonce` as the value. The default nonce field name is `partial_pipeline_confirm_nonce`. Other integrations should implement both Strategy hooks: `partial_pipeline_external_resume_confirmation()` to render the local confirmation response and `partial_pipeline_external_resume_confirmed()` to verify the follow-up request. Check the [example applications](https://github.com/python-social-auth/social-examples) for more detailed usage examples. ## Email validation There’s a pipeline to validate email addresses, but it relies a lot on your project. The pipeline is at `social_core.pipeline.mail.mail_validation` and it’s a partial pipeline, it will return a redirect to the URL defined by the EMAIL_VALIDATION_URL setting. For Django you can use a view name as the value for this setting. You can use this redirect to tell the users that an email validation was sent to them. If you want to mention the email address you can get it from the session under the key `email_validation_address`. In order to send the validation [python-social-auth](https://github.com/python-social-auth) needs a function that will take care of it, this function is defined by the developer with the setting `SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION`. It should be an import path. This function should take four arguments `strategy`, `backend`, `code` and `partial_token`. `partial_token` is the same token used on other partials functions that can be used to restart a halted flow. The built-in mail validation step is an externally resumable partial. Opening the validation link will first show the local confirmation response provided by the active Strategy. After confirmation, the pipeline receives the original `verification_code` and `partial_token` through `strategy.request_data()`. `code` is a model instance used to validate the email address, it contains four fields: `code = '...'` : Holds an `uuid.uuid4()` value and it’s the code used to identify the validation process. `email = '...'` : Email address trying to be validate. `verified = True / False` : Flag marking if the email was verified or not. `timestamp` : Creation time used to enforce the code’s lifetime. Email validation codes are single-use and expire after seven days by default. Set their lifetime in seconds with: ```default SOCIAL_AUTH_EMAIL_VALIDATION_EXPIRED_THRESHOLD = 604800 ``` Set this to `None` or `0` to disable expiry. Codes are expired once their creation time plus this lifetime is reached. Undated codes are rejected when expiry is enabled, and existing codes older than the configured lifetime can no longer be used. See [Storage](storage.html.md) for timestamp persistence requirements. Expiry is checked when the code is validated, independently of scheduled database cleanup. It does not delete expired codes or limit the lifetime of other partial pipeline steps. Django’s `clearsocial` command handles retention of old unused codes and partials separately. You should use the code in this instance to build the link for email validation which should go to `/complete/email?verification_code=&partial_token=`. If you are using Django, you can do it with: ```default from django.core.urlresolvers import reverse url = strategy.build_absolute_uri( reverse('social:complete', args=(strategy.backend_name,)) ) + '?verification_code=' + code.code + '&partial_token=' + partial_token ``` On Flask: ```default from flask import url_for url = url_for('social.complete', backend=strategy.backend_name, _external=True) + '?verification_code=' + code.code + '&partial_token=' + partial_token ``` For Django, resume email validation through `social:complete` so the normal pipeline completion selects the login backend. If you implement a separate account activation view that calls `django.contrib.auth.login()` directly, follow [Logging in users from custom views](configuration/django.html.md#django-custom-login) when multiple backends are configured. This pipeline can be used globally with any backend if this setting is defined: ```default SOCIAL_AUTH_FORCE_EMAIL_VALIDATION = True ``` Or individually by defining the setting per backend basis like `SOCIAL_AUTH_TWITTER_FORCE_EMAIL_VALIDATION = True`. # Extending the Pipeline The pipeline system is designed for extensibility. You can add custom functions to: * Modify authentication data * Create or update related model instances * Request additional user information * Implement custom authorization logic * Integrate with external systems ## Steps to Add a Custom Pipeline Function 1. **Write your function** with the appropriate signature 2. **Place it in an importable location** in your project 3. **Add it to the pipeline** in your settings at the appropriate position #### IMPORTANT Function placement matters! The order determines what data is available. For example, placing your function after `create_user` ensures you receive a `user` instance rather than `None`. ## Writing Custom Pipeline Functions ### Function Signature Your function should accept the common parameters and `**kwargs`: ```default def my_pipeline_function(strategy, backend, user=None, **kwargs): # Your code here pass ``` #### TIP Always include `**kwargs` to handle additional parameters from other pipeline functions or future versions. See [Common Function Parameters](pipeline.html.md#common-function-parameters) for details on the parameters available to pipeline functions. ## Practical Example: Saving User Profile Data This example creates a `Profile` instance to store additional user information from Facebook. **Understanding the Facebook Response** The `response` parameter from Facebook typically looks like: ```default { 'username': 'foobar', 'access_token': 'CAAD...', 'first_name': 'Foo', 'last_name': 'Bar', 'verified': True, 'name': 'Foo Bar', 'locale': 'en_US', 'gender': 'male', 'expires': '5183999', 'email': 'foo@bar.com', 'updated_time': '2014-01-14T15:58:35+0000', 'link': 'https://www.facebook.com/foobar', 'timezone': -3, 'id': '100000126636010', } ``` Let’s say we are interested in storing the user profile link, the gender and the timezone in our `Profile` model: ```default def save_profile(backend, user, response, *args, **kwargs): if backend.name == 'facebook': profile = user.get_profile() if profile is None: profile = Profile(user_id=user.id) profile.gender = response.get('gender') profile.link = response.get('link') profile.timezone = response.get('timezone') profile.save() ``` Now all that’s needed is to tell `python-social-auth` to use our function in the pipeline. Since the function uses user instance, we need to put it after `social_core.pipeline.user.create_user`: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.user.create_user', 'path.to.save_profile', # <--- set the path to the function 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` **Passing Data Forward** The function above returns `None`, which is fine if subsequent functions don’t need the profile. To make the `profile` available to later pipeline functions, return a dict: ```default def save_profile(backend, user, response, *args, **kwargs): if backend.name == 'facebook': profile = user.get_profile() if profile is None: profile = Profile(user_id=user.id) profile.gender = response.get('gender') profile.link = response.get('link') profile.timezone = response.get('timezone') profile.save() return {'profile': profile} # Make profile available to next functions ``` ## Common Patterns and Tips **Conditional Execution** Check the backend name to run logic for specific providers: ```default def my_function(backend, **kwargs): if backend.name == 'google-oauth2': # Google-specific logic pass elif backend.name == 'facebook': # Facebook-specific logic pass ``` **Accessing Settings** Use the strategy to access settings: ```default def my_function(strategy, **kwargs): custom_setting = strategy.setting('MY_CUSTOM_SETTING') ``` **Making API Calls** Use the access token from `response` to call provider APIs: ```default def fetch_additional_data(backend, response, **kwargs): access_token = response.get('access_token') # Make API call using the token import requests api_response = requests.get( 'https://provider-api.com/endpoint', headers={'Authorization': f'Bearer {access_token}'} ) return {'additional_data': api_response.json()} ``` **Debugging** Log pipeline execution to understand the flow: ```default import logging logger = logging.getLogger(__name__) def my_function(user, **kwargs): logger.debug(f'Pipeline function called for user: {user}') logger.debug(f'Available kwargs: {kwargs.keys()}') # Your logic here ``` # security.html.md # Security considerations ## Stable social account identifiers Social authentication associations are authorization bindings. Their `uid` must therefore come from a provider identifier that is immutable and cannot be reassigned, rather than a display name, email address, UPN, or other human-readable login name. Bundled backends use stable provider identifiers where available, including OIDC `sub` claims, provider account IDs, UUIDs, and verified OpenID identity URLs. Applications overriding a backend’s `ID_KEY` are responsible for ensuring the selected claim has the same stability properties. Backends whose provider responses expose no stable identifier, including Drip, Last.fm, and Mixcloud, are association-only and require an authenticated local user. When upgrading an existing deployment, read [the configurable user ID key documentation](configuration/settings.html.md#configurable-user-id-key) before authenticating users. The default compatibility migration preserves existing logins but accepts a one-time first-login race for associations that lack stored stable identity data. Security-sensitive deployments should disable that fallback and migrate the affected records administratively. ## Host header validation The library may use the incoming HTTP `Host` header when generating absolute URLs or redirects during the authentication and authorization flow. If the `Host` header is not validated by the deployment stack, it may allow host header injection attacks. This is a deployment and configuration concern rather than a defect in the library itself. The behavior is intentional, as the library needs to construct absolute URLs for OAuth callbacks and redirects. Proper upstream validation is required to ensure that only legitimate `Host` header values are accepted by your application. ## Reverse proxy configuration When deploying behind a reverse proxy (such as nginx, Apache, HAProxy, or a cloud load balancer), the proxy must validate the Host header before forwarding requests to the application. Key requirements: * **Validate the Host header**: Only expected hostnames should be forwarded upstream to the application. Requests with unexpected or malicious Host values should be rejected by the proxy. * **Forwarded headers**: If your deployment uses forwarded headers such as `X-Forwarded-Host` or the standard `Forwarded` header: * These headers must be accepted **only from trusted proxies**. * They must **not** be blindly trusted from direct client requests. * They must be configured explicitly in the proxy configuration. #### NOTE Configuration syntax varies across reverse proxy implementations. Consult your proxy’s documentation for Host header validation and forwarded header handling. ## Django configuration When using Python Social Auth with Django, proper Host header validation must be configured at the application level using Django’s built-in security features. Key requirements: * **Configure ALLOWED_HOSTS**: The `ALLOWED_HOSTS` setting must be explicitly configured with the canonical hostname(s) for your application. For example: ```default ALLOWED_HOSTS = ['example.com', 'www.example.com'] ``` * **Never use wildcard in production**: The wildcard value `"*"` must not be used in production environments, as it disables Host header validation entirely. * **Host validation behind proxies**: Host validation must remain enabled even when the application is deployed behind a reverse proxy. Do not disable `ALLOWED_HOSTS` validation based on the assumption that the proxy will handle it. * **Forwarded header settings**: If your deployment uses forwarded headers, configure Django’s `USE_X_FORWARDED_HOST` setting carefully. This setting should only be enabled when: * The application is behind a trusted reverse proxy. * The proxy is properly configured to set or strip forwarded headers. * The proxy prevents clients from sending malicious forwarded headers directly. For more information on Django security settings, refer to the [Django security documentation](https://docs.djangoproject.com/en/stable/topics/security/). # storage.html.md # Storage Different frameworks support different ORMs, Storage solves the different interfaces moving the common API to mixins classes. These mixins are used on apps when defining the different models used by `python-social-auth`. ## Social User This model associates a social account data with a user in the system, it contains the provider name, the user ID (`uid`) which identifies the social account in the remote provider, and `id_key` naming the provider field from which that ID was obtained. It also contains JSON-encoded `extra_data` with additional provider information. Existing rows created before `id_key` was introduced use an empty string until social-core migrates them. When implementing this model, it must inherits from [UserMixin](https://github.com/python-social-auth/social-core/blob/master/social_core/storage.py#L21) and extend the needed methods: * Username: ```default @classmethod def get_username(cls, user): """Return the username for given user""" raise NotImplementedError('Implement in subclass') @classmethod def username_max_length(cls): """Return the max length for username""" raise NotImplementedError('Implement in subclass') ``` * User model: ```default @classmethod def user_model(cls): """Return the user model""" raise NotImplementedError('Implement in subclass') @classmethod def changed(cls, user): """The given user instance is ready to be saved""" raise NotImplementedError('Implement in subclass') @classmethod def user_exists(cls, username): """ Return True/False if a User instance exists with the given arguments. Arguments are directly passed to filter() manager method. """ raise NotImplementedError('Implement in subclass') @classmethod def create_user(cls, username, email=None): """Create a user with given username and (optional) email""" raise NotImplementedError('Implement in subclass') @classmethod def get_user(cls, pk): """Return user instance for given id""" raise NotImplementedError('Implement in subclass') ``` * Social user: ```default @classmethod def get_social_auth(cls, provider, uid, id_key=None): """Return UserSocialAuth for the provider, uid, and optional key""" raise NotImplementedError('Implement in subclass') @classmethod def get_social_auth_by_extra_data(cls, provider, key, value, id_key=''): """Return one unambiguous association matching stable provider data""" raise NotImplementedError('Implement in subclass') @classmethod def get_social_auth_for_user(cls, user): """Return all the UserSocialAuth instances for given user""" raise NotImplementedError('Implement in subclass') @classmethod def create_social_auth(cls, user, uid, provider, id_key=''): """Create a UserSocialAuth instance for given user""" raise NotImplementedError('Implement in subclass') @classmethod def migrate_social_auth(cls, social, uid, id_key): """Atomically replace the association identifier and its key""" raise NotImplementedError('Implement in subclass') ``` Identifier migration must preserve the storage’s provider/UID uniqueness guarantee, lock the association while updating it, and fail rather than select an arbitrary row when stored provider data matches multiple associations. * Social disconnection: ```default @classmethod def allowed_to_disconnect(cls, user, backend_name, association_id=None): """Return if it's safe to disconnect the social account for the given user""" raise NotImplementedError('Implement in subclass') @classmethod def disconnect(cls, name, user, association_id=None): """Disconnect the social account for the given user""" raise NotImplementedError('Implement in subclass') ``` ## Nonce This is a helper class for OpenID mechanism, it stores a one-use number, shouldn’t be used by the project since it’s for internal use only. When implementing this model, it must inherit from [NonceMixin](https://github.com/python-social-auth/social-core/blob/master/social_core/storage.py#L166), and override the needed methods: ```default @classmethod def use(cls, server_url, timestamp, salt): """Create a Nonce instance""" raise NotImplementedError('Implement in subclass') @classmethod def get(cls, server_url, salt): """Retrieve a Nonce instance""" raise NotImplementedError('Implement in subclass') @classmethod def delete(cls, nonce): """Delete a Nonce instance""" raise NotImplementedError('Implement in subclass') ``` ## Association This internal model stores OpenID protocol associations and temporary OpenID Connect login nonces. It is separate from the model linking a user to a provider. For OIDC, `handle` stores the nonce, `secret` is empty, and `assoc_type` stores OAuth state. `issued` is the integer Unix creation timestamp and `lifetime` is the duration in seconds. `AssociationMixin.is_expired(now=None)` returns whether the lifetime has elapsed, including the exact expiry boundary. Nonpositive lifetimes are expired. OIDC validation removes matching expired records and rejects the login. Storage integrations must preserve `issued` and `lifetime`. During upgrade, existing OIDC nonce records with an empty secret and both values zero can receive the upgrade timestamp and a 1,800-second grace period. Other unbounded records are rejected. Stop old login-serving processes before this conversion so they do not create additional undated nonces afterward. Django provides `Association.cleanup_expired(now=None)`, which deletes expired OpenID associations and OIDC nonces and returns the deleted record count. `now` is an optional integer Unix timestamp; it defaults to the current time. Other integrations should implement scheduled cleanup using the same expiry rule. OpenID’s existing on-demand cleanup only visits associations for the provider being queried. When implementing this model, it must inherits from [AssociationMixin](https://github.com/python-social-auth/social-core/blob/master/social_core/storage.py#L178), and override the needed methods: ```default @classmethod def store(cls, server_url, association): """Create an Association instance""" raise NotImplementedError('Implement in subclass') @classmethod def get(cls, *args, **kwargs): """Get an Association instance""" raise NotImplementedError('Implement in subclass') @classmethod def remove(cls, ids_to_delete): """Remove an Association instance""" raise NotImplementedError('Implement in subclass') ``` ## Validation code This class is used to keep track of email validations codes following the usual email validation mechanism of sending an email to the user with a unique code. This model is used by the partial pipeline `social_core.pipeline.mail.mail_validation`. Check the docs at *Email validation* in [pipeline docs](pipeline.html#email-validation). The model must inherit from `CodeMixin` and persist the `email`, `code`, `verified`, and `timestamp` attributes. `make_code()` initializes `timestamp` with the creation time in UTC. A framework-managed creation timestamp can also be used. Naive timestamps are interpreted as UTC by the default `is_expired(seconds)` implementation; override this method if your storage uses another timezone. The Django integration interprets naive timestamps in Django’s configured timezone. Codes without a timestamp are rejected when expiry is enabled. Existing storage integrations must add timestamp persistence and migrate existing data, or have users request new codes. Do not assign a new creation time to old codes. The storage lookup method must also be overridden: ```default @classmethod def get_code(cls, code): """Return the Code instance with the given code value""" raise NotImplementedError('Implement in subclass') ``` ## Storage interface There’s a helper class used by strategies to hide the real models names under a common API, an instance of this class is used by strategies to access the storage modules. When implementing this class it must inherits from [BaseStorage](https://github.com/python-social-auth/social-core/blob/master/social_core/storage.py#L248), add the needed models references and implement the needed method: ```default class StorageImplementation(BaseStorage): user = UserModel nonce = NonceModel association = AssociationModel code = CodeModel @classmethod def is_integrity_error(cls, exception): """Check if given exception flags an integrity error in the DB""" raise NotImplementedError('Implement in subclass') ``` ## SQLAlchemy and Django mixins Currently there are partial implementations of mixins for [SQLAlchemy ORM](https://github.com/python-social-auth/social-storage-sqlalchemy/blob/master/social_sqlalchemy/storage.py) and [Django ORM](https://github.com/python-social-auth/social-app-django/blob/master/social_django/storage.py) with common code used later on current implemented applications. #### NOTE When using [SQLAlchemy ORM](https://github.com/python-social-auth/social-storage-sqlalchemy/blob/master/social_sqlalchemy/storage.py) and `ZopeTransactionExtension`, it’s recommended to use the [transaction](https://pypi.python.org/pypi/transaction) application to handle them. ## Models Examples Check for current implementations for [Django App](https://github.com/python-social-auth/social-app-django/blob/master/social_django/models.py), [Flask App](https://github.com/python-social-auth/social-app-flask/blob/master/social_flask/models.py), [Pyramid App](https://github.com/python-social-auth/social-app-pyramid/blob/master/social_pyramid/models.py), and [Webpy App](https://github.com/python-social-auth/social-app-webpy/blob/master/social_webpy/models.py) for examples of implementations. # strategies.html.md # Strategies Different strategies are defined to encapsulate the different frameworks capabilities under a common API to reuse as much code as possible. ## Description A strategy’s responsibility is to provide access to: * Request data and host information and URI building * Session access * Project settings * Response types (HTML and redirects) * HTML rendering Different frameworks implement these features on different ways, thus the need for these interfaces. ## Implementing a new Strategy The following methods must be defined on strategies sub-classes. Request: ```default def get_request_data(self, merge=True): """Return current framework request data (POST or GET)""" raise NotImplementedError('Implement in subclass') def request_host(self): """Return current host value""" raise NotImplementedError('Implement in subclass') def build_absolute_uri(self, path=None): """Build absolute URI with given (optional) path""" raise NotImplementedError('Implement in subclass') ``` Session: ```default def session_get(self, name): """Return session value for given key""" raise NotImplementedError('Implement in subclass') def session_set(self, name, value): """Set session value for given key""" raise NotImplementedError('Implement in subclass') def session_pop(self, name): """Pop session value for given key""" raise NotImplementedError('Implement in subclass') ``` Settings: ```default def get_setting(self, name): """Return value for given setting name""" raise NotImplementedError('Implement in subclass') ``` Responses: ```default def html(self, content): """Return HTTP response with given content""" raise NotImplementedError('Implement in subclass') def redirect(self, url): """Return a response redirect to the given URL""" raise NotImplementedError('Implement in subclass') def render_html(self, tpl=None, html=None, context=None): """Render given template or raw html with given context""" raise NotImplementedError('Implement in subclass') ``` ## Effective pipeline request data `strategy.request` holds the native framework request, when the integration provides one. It is never replaced by saved partial-pipeline parameters. `strategy.get_request_data(merge=True)` reads the current framework request. With `merge=False`, it reads the data for the current request method, following the framework integration’s existing behavior. Custom strategies implement this hook instead of overriding `request_data()`. `strategy.request_data(merge=True)` returns the effective parameters for the active pipeline. During a partial resume, this includes any confirmed data replayed from an external validation link. Both values of `merge` return the same effective mapping during replay, because saved data no longer has a separate GET or POST origin. Use `get_request_data()`, `request_get()`, or `request_post()` when the current framework request is required. The effective mapping is scoped to execution of the resumed authentication or disconnect pipeline. The previous mapping is restored when execution completes, returns a response, or raises an exception. Nested executions restore the outer mapping. Integration code can establish the same scope with `strategy.pipeline_request_data(data)` as a context manager. ## Migrating to social-auth-core 6 and social-auth-app-django 7 * Rename custom `request_data()` overrides to `get_request_data()`. Keep framework extraction, validation, and application-specific defaults in that hook; allow the inherited `request_data()` method to handle replay. * Replace pipeline `request` parameters and `kwargs['request']` reads with `strategy.request_data()` for effective parameters, or `strategy.request` for a native framework request. Pipeline steps no longer receive an automatic `request` argument. * Upgrade framework adapters together with social-auth-core. Adapters that override the old hook must migrate before using core 6. Partial request data is stored separately from pipeline arguments. Existing partials with a request mapping in `kwargs['request']` are converted when loaded, so upgrading does not require a database schema migration or discarding pending authentication flows. Partials are bound to their authentication or disconnect pipeline. Legacy disconnect partials without a pipeline type must restart the disconnect flow so its permission checks run. # tests.html.md # Testing python-social-auth Testing the application is fairly simple, just met the dependencies and run the testing suite. The testing suite uses [HTTPretty](https://github.com/gabrielfalcao/HTTPretty) to mock server responses, it’s not a live test against the providers API, to do it that way, a browser and a tool like Selenium are needed, that’s slow, prone to errors on some cases, and some of the application examples must be running to perform the testing. Plus real Key and Secret pairs, in the end it’s a mess to test functionality which is the real point. By mocking the server responses, we can test the backends functionality (and other areas too) easily and quick. ## Installing dependencies Go to the [tests](https://github.com/python-social-auth/social-core/tree/master/social_core/tests) directory and install the dependencies listed in the [requirements.txt](https://github.com/python-social-auth/social-core/blob/master/social_core/tests/requirements.txt). Then run with `nosetests` command, or with the `run_tests.sh` script. ## Tox You can use [tox](http://tox.readthedocs.org/) to test compatibility against all supported Python versions: ```bash $ pip install tox # if not present $ tox ``` ## Pending At the moment only OAuth1, OAuth2 and OpenID backends are being tested, and just login and partial pipeline features are covered by the test. There’s still a lot to work on, like: * Frameworks support # thanks.html.md # Thanks [python-social-auth](https://github.com/python-social-auth) is the result of almost 3 years of development done on [django-social-auth](https://github.com/omab/django-social-auth) which is the result of my initial work and the thousands lines of code contributed by so many developers that took time to work on improvements, report bugs and hunt them down to propose a fix. So, here is a big list of users that helped to build this library (if somebody is missed let me know and I’ll update the list): * [kjoconnor](https://github.com/kjoconnor) * [krvss](https://github.com/krvss) * [estebistec](https://github.com/estebistec) * [mrmch](https://github.com/mrmch) * [uruz](https://github.com/uruz) * [maraujop](https://github.com/maraujop) * [bacher09](https://github.com/bacher09) * [dokterbob](https://github.com/dokterbob) * [hassek](https://github.com/hassek) * [andrusha](https://github.com/andrusha) * [vicalloy](https://github.com/vicalloy) * [caioariede](https://github.com/caioariede) * [danielgtaylor](https://github.com/danielgtaylor) * [stephenmcd](https://github.com/stephenmcd) * [gugu](https://github.com/gugu) * [yrik](https://github.com/yrik) * [dhendo](https://github.com/dhendo) * [yekibud](https://github.com/yekibud) * [tmackenzie](https://github.com/tmackenzie) * [LuanP](https://github.com/LuanP) * [jezdez](https://github.com/jezdez) * [serdardalgic](https://github.com/serdardalgic) * [Jolmberg](https://github.com/Jolmberg) * [ChrisCooper](https://github.com/ChrisCooper) * [marselester](https://github.com/marselester) * [eshellman](https://github.com/eshellman) * [micrypt](https://github.com/micrypt) * [revolunet](https://github.com/revolunet) * [dasevilla](https://github.com/dasevilla) * [seansay](https://github.com/seansay) * [hepochen](https://github.com/hepochen) * [gibuloto](https://github.com/gibuloto) * [crodjer](https://github.com/crodjer) * [sidmitra](https://github.com/sidmitra) * [ryr](https://github.com/ryr) * [inve1](https://github.com/inve1) * [mback2k](https://github.com/mback2k) * [hannesstruss](https://github.com/hannesstruss) * [NorthIsUp](https://github.com/NorthIsUp) * [tonyxiao](https://github.com/tonyxiao) * [dhepper](https://github.com/dhepper) * [Troytft](https://github.com/Troytft) * [gardaud](https://github.com/gardaud) * [oinopion](https://github.com/oinopion) * [gameguy43](https://github.com/gameguy43) * [vinigracindo](https://github.com/vinigracindo) * [syabro](https://github.com/syabro) * [bashmish](https://github.com/bashmish) * [ggreer](https://github.com/ggreer) * [avillavi](https://github.com/avillavi) * [r4vi](https://github.com/r4vi) * [roderyc](https://github.com/roderyc) * [daonb](https://github.com/daonb) * [slon7](https://github.com/slon7) * [JasonGiedymin](https://github.com/JasonGiedymin) * [tymofij](https://github.com/tymofij) * [Cassus](https://github.com/Cassus) * [martey](https://github.com/martey) * [t0m](https://github.com/t0m) * [johnthedebs](https://github.com/johnthedebs) * [jammons](https://github.com/jammons) * [stefanw](https://github.com/stefanw) * [maxgrosse](https://github.com/maxgrosse) * [mattucf](https://github.com/mattucf) * [tadeo](https://github.com/tadeo) * [haxoza](https://github.com/haxoza) * [bradbeattie](https://github.com/bradbeattie) * [henward0](https://github.com/henward0) * [bernardokyotoku](https://github.com/bernardokyotoku) * [czpython](https://github.com/czpython) * [glasscube42](https://github.com/glasscube42) * [assiotis](https://github.com/assiotis) * [dbaxa](https://github.com/dbaxa) * [JasonSanford](https://github.com/JasonSanford) * [originell](https://github.com/originell) * [cihann](https://github.com/cihann) * [niftynei](https://github.com/niftynei) * [mikesun](https://github.com/mikesun) * [1st](https://github.com/1st) * [betonimig](https://github.com/betonimig) * [ozexpert](https://github.com/ozexpert) * [stephenLee](https://github.com/stephenLee) * [julianvargasalvarez](https://github.com/julianvargasalvarez) * [youngrok](https://github.com/youngrok) * [garrypolley](https://github.com/garrypolley) * [amirouche](https://github.com/amirouche) * [fmoga](https://github.com/fmoga) * [pydanny](https://github.com/pydanny) * [pygeek](https://github.com/pygeek) * [dgouldin](https://github.com/dgouldin) * [kotslon](https://github.com/kotslon) * [kirkchris](https://github.com/kirkchris) * [barracel](https://github.com/barracel) * [sayar](https://github.com/sayar) * [kulbir](https://github.com/kulbir) * [Morgul](https://github.com/Morgul) * [spstpl](https://github.com/spstpl) * [bluszcz](https://github.com/bluszcz) * [vbsteven](https://github.com/vbsteven) * [sbassi](https://github.com/sbassi) * [aspcanada](https://github.com/aspcanada) * [browniebroke](https://github.com/browniebroke) * [eshaan7](https://github.com/eshaan7) * [amitray007](https://github.com/amitray007) # use_cases.html.md # Use Cases Some miscellaneous options and use cases for [python-social-auth](https://github.com/python-social-auth). ## Return the user to the original page There’s a common scenario to return the user back to the original page from where they requested to login. For that purpose, the usual `next` argument is used. The value of this parameter will be stored in the session and later used to redirect the user when login was successful. In order to use it, just define it with your login request. For instance, when using Django: ```default
    {% csrf_token %}
    ``` ## Pass custom GET/POST parameters and retrieve them on authentication In some cases, you might need to send data with the login request, and retrieve it while processing the after-effect. For example, for conditionally executing code in custom pipelines. In such cases, add it to `SOCIAL_AUTH_FIELDS_STORED_IN_SESSION`. In your settings: ```default SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['key'] ``` In a Django template: ```default
    {% csrf_token %}
    ``` In your custom pipeline, retrieve it using: ```default strategy.session_get('key') ``` ## Associate users by email Sometimes it’s desirable that social accounts are automatically associated if the email already matches a user account. For example, if a user signed up with their Facebook account, then logged out and next time tries to use Google OAuth2 to login, it could be nice (if both social sites have the same email address configured) that the user gets into their initial account created by Facebook backend. This scenario is possible by enabling the `associate_by_email` pipeline function, like this: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.social_auth.associate_by_email', # <--- enable this one 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` This feature is disabled by default because it’s not 100% secure to automate this process with all the backends. Not all the providers will validate your email account and others users could take advantage of that. Take for instance User A registered in your site with the email `foo@bar.com`. Then a malicious user registers into another provider that doesn’t validate their email with that same account. Finally this user will turn to your site (which supports that provider) and sign up to it, since the email is the same, the malicious user will take control over the User A account. ## Signup by OAuth access_token It’s a common scenario that mobile applications will use an SDK to signup a user within the app, but that signup won’t be reflected by [python-social-auth](https://github.com/python-social-auth) unless the corresponding database entries are created. In order to do so, it’s possible to create a view / route that creates those entries by a given `access_token`. Take the following code for instance (the code follows Django conventions, but versions for others frameworks can be implemented easily): ```default from django.contrib.auth import login from social_django.utils import psa # Define an URL entry to point to this view, call it passing the # access_token parameter like ?access_token=. The URL entry must # contain the backend, like this: # # path('register-by-token//', # register_by_access_token, # name='register_by_access_token') @psa('social:complete') def register_by_access_token(request, backend): # This view expects an access_token GET parameter, if it's needed, # request.backend and request.strategy will be loaded with the current # backend and strategy. token = request.GET.get('access_token') user = request.backend.do_auth(token) if user: login(request, user) return 'OK' else: return 'ERROR' ``` The snippet above is quite simple, it doesn’t return JSON and usually this call will be done by AJAX. It doesn’t return the user information, but that’s something that can be extended and filled to suit the project where it’s going to be used. **Note**: when dealing with `OAuth1`, the `access_token` is : actually a query-string composed by `oauth_token` and `oauth_token_secret`, [python-social-auth](https://github.com/python-social-auth) expects this to be a `dict` with those keys, but if an string is detected, it will treat it as a query string in the form `oauth_token=123&oauth_token_secret=456`. ## Multiple scopes per provider At the moment [python-social-auth](https://github.com/python-social-auth) doesn’t provide a method to define multiple scopes for single backend, this is usually desired since it’s recommended to ask the user for the minimum scope possible and increase the access when it’s really needed. It’s possible to add a new backend extending the original one to accomplish that behavior. There are two ways to do it. 1. Overriding `get_scope()` method: ```default from social_core.backends.facebook import FacebookOAuth2 class CustomFacebookOAuth2(FacebookOauth2): def get_scope(self): scope = super(CustomFacebookOAuth2, self).get_scope() if self.data.get('extrascope'): scope = scope + [('foo', 'bar')] return scope ``` This method is quite simple, it overrides the method that returns the scope value in a backend (`get_scope()`) and adds extra values to the list if it was indicated by a parameter in the `GET` or `POST` data (`self.data`). Put this new backend in some place in your project and replace the original `FacebookOAuth2` in `AUTHENTICATION_BACKENDS` with this new version. When overriding this method, take into account that the default output the base class for `get_scope()` is the raw value from the settings (whatever they are defined), doing this will actually update the value in your settings for all the users: ```default scope = super(CustomFacebookOAuth2, self).get_scope() scope += ['foo', 'bar'] ``` Instead do it like this: ```default scope = super(CustomFacebookOAuth2, self).get_scope() scope = scope + ['foo', 'bar'] ``` 2. It’s possible to do the same by defining a second backend which extends from the original but overrides the name, this will imply new URLs and also new settings for the new backend (since the name is used to build the settings names), it also implies a new application in the provider since not all providers give you the option of defining multiple redirect URLs. To do it just add a backend like: ```default from social_core.backends.facebook import FacebookOAuth2 class CustomFacebookOAuth2(FacebookOauth2): name = 'facebook-custom' ``` Put this new backend in some place in your project keeping the original `FacebookOAuth2` in `AUTHENTICATION_BACKENDS`. Now a new set of URLs will be functional: ```default /login/facebook-custom /complete/facebook-custom /disconnect/facebook-custom ``` And also a new set of settings: ```default SOCIAL_AUTH_FACEBOOK_CUSTOM_KEY = '...' SOCIAL_AUTH_FACEBOOK_CUSTOM_SECRET = '...' SOCIAL_AUTH_FACEBOOK_CUSTOM_SCOPE = [...] ``` When the extra permissions are needed, start authentication with the new backend and then get the social auth entry for it with `user.social_auth.get(provider='facebook-custom')` and use the `access_token` in it. In Django templates, start the flow with a POST form: ```default
    {% csrf_token %}
    ``` ## Enable a user to choose a username from their World of Warcraft characters If you want to register new users on your site via battle.net, you can enable these users to choose a username from their own World-of-Warcraft characters. To do this, use the `battlenet-oauth2` backend along with a small form to choose the username. The form is rendered via a partial pipeline item like this: ```default @partial def pick_character_name(backend, details, response, is_new=False, *args, **kwargs): if backend.name == 'battlenet-oauth2' and is_new: data = backend.strategy.request_data() if data.get('character_name') is None: # New user and didn't pick a character name yet, so we render # and send a form to pick one. The form must do a POST/GET # request to the same URL (/complete/battlenet-oauth2/). In this # example we expect the user option under the key: # character_name # you have to filter the result list according to your needs. # In this example, only guild members are allowed to sign up. char_list = [ c['name'] for c in backend.get_characters(response.get('access_token')) if 'guild' in c and c['guild'] == '' ] return render_to_response('pick_character_form.html', {'charlist': char_list, }) else: # The user selected a character name return {'username': data.get('character_name')} ``` Don’t forget to add the partial to the pipeline: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'path.to.pick_character_name', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` It needs to be somewhere before create_user because the partial will change the username according to the users choice. ## Re-prompt Google OAuth2 users to refresh the `refresh_token` A `refresh_token` also expire, a `refresh_token` can be lost, but they can also be refreshed (or re-fetched) if you ask to Google the right way. In order to do so, set this setting: ```default SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = { 'access_type': 'offline', 'approval_prompt': 'auto' } ``` Then show users a form that starts Google OAuth2 with `approval_prompt=force`. In Django templates, submit the value in the POST body: ```default
    {% csrf_token %}
    ``` If you want to refresh the `refresh_token` only on those users that don’t have it, redirect them to a page that renders the form above with a pipeline function: ```default def redirect_if_no_refresh_token(backend, response, social, *args, **kwargs): if backend.name == 'google-oauth2' and social and \ response.get('refresh_token') is None and \ social.extra_data.get('refresh_token') is None: return redirect('/refresh-google-access/') ``` Set this pipeline after `social_user`: ```default SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_names', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'path.to.redirect_if_no_refresh_token', 'social_core.pipeline.user.get_username', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', ) ``` ## Improve unicode cleanup from usernames It’s possible to improve the username cleanup by using an external library like [Unidecode](https://pypi.org/project/Unidecode/) or [Text-Unicode](https://github.com/kmike/text-unidecode/). You can integrate these by using the SOCIAL_AUTH_CLEAN_USERNAME_FUNCTION documented at [Username Generation](configuration/settings.html#username-generation) section. For instance, this will do the work: ```default SOCIAL_AUTH_CLEAN_USERNAME_FUNCTION = 'unidecode.unidecode' ```