📄 auth.cpython-312.pyc
/home/palash/git/local-ai/server/__pycache__/auth.cpython-312.pyc
Language: pyc • Lines: 241
�

���j�����dZddlZddlZddlZddlZddlmZddlZddlmZm	Z	m
Z
mZmZm
Z
dddd�Zdadaej"�Zd	Zd
�Zd�Zd�Zd
�Zd�Zd�Zd�Zd�Zd�Zd�Zy)u�Unified RBAC / SSO identity layer backed by Authentik.

This is the SINGLE identity provider for every app on the box. There is no
more ``users.json``; users, passwords and roles live in Authentik.

Two identity paths converge here:

1. Browser users — nginx runs ``auth_request`` against the Authentik proxy
   outpost and forwards the ``X-Authentik-*`` claim headers upstream. Backends
   trust those headers (only nginx can reach the app ports).

2. Machine agents (self-chat.py) — obtain an OIDC access token via Authentik's
   OAuth2 password grant and send it as ``Authorization: Bearer <jwt>``.
   Backends verify the JWT signature against Authentik's JWKS.

The resolved identity is always a dict::

    {
        "username": str,
        "email": str,
        "name": str,
        "groups": [str, ...],   # raw Authentik group names
        "role": "admin" | "premium" | "free",
        "uid": str,             # Authentik user UUID (unique id across renames)
    }
�N)�PyJWK)�AUTH_AGENTS_CLIENT_ID�AUTH_AGENTS_CLIENT_SECRET�AUTH_AGENTS_ISSUER�AUTH_AGENTS_JWKS_URL�AUTH_AGENTS_TOKEN_URL�AUTH_ROLE_GROUPS��)�free�premium�admingi,c�&�|xsdD]}|s�|cSy)N�r)�seq�items  �(/home/palash/git/local-ai/server/auth.py�_firstr6s"���	�r�����K���c���d}d}|xsdD][}tj|j�j��}|s�7tj|d�|kDs�Q|}t|}�]|S)zEMap Authentik group names to the app role scale (free/premium/admin).r�����r)r	�get�lower�strip�_ROLE_LEVEL)�groups�best�
best_level�g�roles     r�role_from_groupsr!=sg���D��J�
�\�r�+���#�#�A�G�G�I�O�O�$5�6���K�O�O�D�"�-�
�:��D�$�T�*�J�	+�
�Krc�n�|sgSt|tttf�rA|D�cgc]5}t	|�j�s�t	|�j���7c}St
jdt	|��D�cgc]#}|j�s�|j���%c}Scc}wcc}w)Nz[|,\s]+)�
isinstance�list�tuple�set�strr�re�split)�rawrs  r�
_split_groupsr+Isx����	��#��e�S�)�*�(+�>�1�s�1�v�|�|�~��A�����>�>�!�x�x�
�C��H�=�K�!�����A�G�G�I�K�K��?��Ks�B-�B-�B2�B2c	�J�t|jd�|jd�g�}|sytt|jd�|jd�g��}||jdd�|jdd�|t|�|jd	d�d
�S)a%Resolve identity from the nginx-injected X-Authentik-* claim headers.

    These headers are set by nginx's auth_request subrequest against the
    Authentik proxy outpost and are only present on nginx-fronted traffic.
    Returns None when absent (e.g. direct localhost calls or agents).
    zX-Authentik-UsernamezX-Authentik-UserNzX-Authentik-GroupszX-Authentik-GroupzX-Authentik-Email�zX-Authentik-NamezX-Authentik-UID��username�email�namerr �uid)rrr+r!)�headersr/rs   r�identity_from_headersr4Qs����	���+�	,�g�k�k�:L�.M�N��H���
�����0�1����/�0�
�	
��F�����0�"�5����.��3�� ��(��{�{�,�b�1�
�rc���t5tj�}t�|tz
tkrtcddd�St
sgcddd�S	t
jt
d��}|j�|j�jdg�a|atcddd�S#tjtf$rtxsga|aY�6wxYw#1swYyxYw)zAReturn the Authentik JWKS key set (cached for _JWKS_TTL seconds).N�)�timeout�keys)�
_jwks_lock�time�_jwks_cache�_jwks_cache_at�	_JWKS_TTLr�requestsr�raise_for_status�json�RequestException�
ValueError)�now�resps  r�_fetch_jwksrEos���
���i�i�k���"�s�^�';�i�'G����$����	!��<�<� 4�a�@�D��!�!�#��)�)�+�/�/�&�"�5�K� �N������)�)�:�6�	!�%�+��K� �N�	!����s6�0C�C�A
B/� C�/%C�C�C�C�C#c	�2�|r|j�jd�sy|jdd�dj�}|syt	�}|std��d}|D]T}	t
j|�j}tj|||jdd�gtdd	i�
�}n|syt|jd�|jd�|jd
�|jd�g�}tt|jd�|jd�g��}||jd
d�|jdd�|t!|�|jdd�d�S#tj$rY��1wxYw)alVerify an ``Authorization: Bearer <jwt>`` token and resolve its identity.

    Verifies the token signature against Authentik's JWKS and enforces the
    issuer (the Authentik OIDC provider URL). Returns None for expired, bogus
    or missing tokens. Raises on transient network failures (so callers can
    treat those distinctly from a plain "no identity").
    zbearer N� r
u9Authentik JWKS unavailable — cannot verify access token�alg�RS256�
verify_audF)�
algorithms�issuer�options�preferred_usernamer/r0�subr�	ak_groupsr-r1r.)r�
startswithr)rrE�RuntimeErrorr�	from_dict�key�jwt�decoderr�InvalidTokenErrorrr+r!)�
authorization�tokenr8�decodedrT�
crypto_keyr/rs        r�identity_from_bearerr\�s����
� 3� 3� 5� @� @�� K������Q�'��*�0�0�2�E����=�D���V�W�W��G����	�����-�1�1�J��j�j����G�G�E�7�3�4�)�%�u�-��G�
������K�K�,�-��K�K�
�#��K�K�� ��K�K���		
��H������H�%�w�{�{�;�'?�@�A��F�����W�b�)����F�B�'�� ��(��{�{�5�"�%�
���!�$�$�	��	�s�(AE?�?F�Fc�V�t|�}|r|St|jdd��S)zBResolve identity from request headers (browser path + agent path).�
Authorizationr-)r4r\r�r3�identitys  r�get_identityra�s*��$�W�-�H��������O�R� @�A�Arc�*�t|�}|r|dSdS)z1Return just the authenticated username (or None).r/N)rar_s  r�get_current_userrc�s���G�$�H�#+�8�J��5��5rc�.�tj|d�S)z;Level for the given role name (free=0, premium=1, admin=2).r)rr)r s r�required_role_levelre�s���?�?�4��#�#rc
��trtstd��tjtd||tt
dd�d��}|j
�|j�}|jd�}|std|����|S)	aExchange agent credentials for an Authentik OIDC access token.

    Used by self-chat.py so the automated agents authenticate through the same
    identity provider as humans. Returns the access token string. Raises on any
    failure so callers can surface a clear error.
    zKAuthentik OIDC not configured (AUTH_AGENTS_TOKEN_URL/AUTH_AGENTS_CLIENT_ID)�passwordzopenid profile email groups)�
grant_typer/rg�	client_id�
client_secret�scope�)�datar7�access_tokenz3Authentik password grant returned no access token: )	rrrRr>�postrr?r@r)r/rgrDrmrns     r�oidc_password_grantrp�s���!�(=��Y�
�	
��=�=��$� � �.�6�2�

���D�	�����9�9�;�D��8�8�N�+�L���P�QU�PV�W�X�X��r)�__doc__r(�	threadingr:rUrr>�
server.configrrrrrr	rr;r<�Lockr9r=rr!r+r4rEr\rarcrerprrr�<module>rus����6
���
������Q��3������
�Y�^�^�
�
��	��	�L��<�(4�nB�6�$�
r