
    qh                     .    S SK r S SKJr   " S S\5      rg)    N)
BaseOAuth2c                   T    \ rS rSrSrSrSrSrS rS r	S r
S	 rS
 rS rS rS rSrg)KeycloakOAuth2   a  Keycloak OAuth2 authentication backend

This backend has been tested working with a standard Keycloak installation,
but you might have to specialize it and tune the parameters per your
configuration.

This setup specializes the OAuth2 backend which, strictly speaking, offers
authorization without authentication capabilities.

Keycloak does offer a full OpenID Connect implementation, but the
implementation is rather labor intensive to implement.

This backend is configured to get an access token instead, and assume that
the access token contains the necessary user details for authentication.

The integrity of the authentication process is followed by public key
verification for the `access_token` along with OpenID Connect specification
`aud` field checking.

To set up, please take the following steps:

1. Create a new Keycloak client in the Clients section:

    a. Choose the `Client ID` in the `General Settings` pane.

    b. Select `Client authentication` and `Authorization` in the
       `Capability config` pane.

2. Configure the following parameters in the Client setup:

    Settings >
        Client ID (copy to settings as `KEY` value)
    Credentials >
        Client Authenticator >
            Use `Client Id and Secret` and copy the `Client secret` value
            to settings as `SECRET` value

3. For the tokens to work with the JWT setup the following configuration has
   to be made in Keycloak:

    Advanced >
        Fine grain OpenID Connect configuration >
            User Info Signed Response Algorithm >
                RS256
    Advanced >
        Fine grain OpenID Connect configuration >
            Request Object Signature Algorithm >
                RS256

4. Re-enable the audience (see https://issues.redhat.com/browse/KEYCLOAK-6638
   for context):

   Go to Client scopes > YOUR-CLIENT-ID-dedicated > Add mapper > Audience, pick
   a name for the mapper and select the Client ID corresponding to your client
   in `Included Client Audience`.

5. Get the public key (copy to settings as `PUBLIC_KEY` value) to be used
   with the backend:

    Realm Settings > Keys > Public key

6. Configure access token fields are configured via the Keycloak Client
   mappers:

    Clients > Client ID > Mappers

They have to include at least the `ID_KEY` value and the dictionary keys
defined in the `get_user_details` method.

7. Configure your web backend. Example setting values for Django settings
   could be:

    SOCIAL_AUTH_KEYCLOAK_KEY = 'example'
    SOCIAL_AUTH_KEYCLOAK_SECRET = '1234abcd-1234-abcd-1234-abcd1234adcd'
    SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY =           'pempublickeythatis2048bitsinbase64andhaseg392characters'
    SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL =           'https://sso.com/auth/realms/example/protocol/openid-connect/auth'
    SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL =           'https://sso.com/auth/realms/example/protocol/openid-connect/token'

8. The default behaviour is to associate users via username field, but you
   can change the key with e.g.

        SOCIAL_AUTH_KEYCLOAK_ID_KEY = 'email'

Please make sure your Keycloak user database and Django user database do not
conflict and that there is no risk of user account hijacking by false
account association.
keycloakusernameFc                 $    U R                  S5      $ )NAUTHORIZATION_URLsettingselfs    O/var/www/html/env/lib/python3.13/site-packages/social_core/backends/keycloak.pyauthorization_url KeycloakOAuth2.authorization_urlf   s    ||/00    c                 $    U R                  S5      $ )NACCESS_TOKEN_URLr   r   s    r   access_token_urlKeycloakOAuth2.access_token_urli   s    ||.//r   c                 $    U R                  S5      $ )NKEYr   r   s    r   audienceKeycloakOAuth2.audiencel   s    ||E""r   c                 "    U R                  SSS9$ )N	ALGORITHMRS256)defaultr   r   s    r   	algorithmKeycloakOAuth2.algorithmo   s    ||K|99r   c                 H    SR                  SU R                  S5      S/5      $ )N
z-----BEGIN PUBLIC KEY-----
PUBLIC_KEYz-----END PUBLIC KEY-----)joinr   r   s    r   
public_keyKeycloakOAuth2.public_keyr   s*    yy,\**
 	
r   c                     [         R                  " UU R                  5       U R                  5       U R	                  5       S9$ )zDecode user data from the access_token

You can specialize this method to e.g. get information
from the Keycloak backend if you do not want to include
the user information in the access_token.
)key
algorithmsr   )jwtdecoder%   r   r   )r   access_tokenargskwargss       r   	user_dataKeycloakOAuth2.user_data{   s5     zz!~~']]_	
 	
r   c                     UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      S.$ )z/Map fields in user_data into Django User fieldspreferred_usernameemailname
given_namefamily_name)r   r3   fullname
first_name	last_name)get)r   responses     r   get_user_detailsKeycloakOAuth2.get_user_details   sK     !%9:\\'* V,",,|4!m4
 	
r   c                 8    UR                  U R                  5      $ )z>Get and associate Django User by the field indicated by ID_KEY)r:   ID_KEY)r   detailsr;   s      r   get_user_idKeycloakOAuth2.get_user_id   s    {{4;;''r    N)__name__
__module____qualname____firstlineno____doc__r4   r?   REDIRECT_STATEr   r   r   r   r%   r/   r<   rA   __static_attributes__rC   r   r   r   r      sB    Yv DFN10#:


(r   r   )r*   social_core.backends.oauthr   r   rC   r   r   <module>rL      s    
 1P(Z P(r   