File size: 2,078 Bytes
8393a26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from fastapi import APIRouter, Request, HTTPException
from authlib.integrations.starlette_client import OAuth
from app.core.config import settings

router = APIRouter()

# Initialize OAuth
oauth = OAuth()

# Register Microsoft Provider
# We use the tenant-specific endpoint for better security and internal organization
CONF_URL = f"https://login.microsoftonline.com/{settings.MS_TENANT_ID}/v2.0/.well-known/openid-configuration"

oauth.register(
    name='microsoft',
    client_id=settings.MS_CLIENT_ID,
    client_secret=settings.MS_CLIENT_SECRET,
    server_metadata_url=CONF_URL,
    client_kwargs={
        'scope': 'openid email profile User.Read'
    }
)

@router.get("/login")
async def login(request: Request):
    """
    Redirects the user to the Microsoft Login page.
    """
    redirect_uri = settings.MS_REDIRECT_URI
    return await oauth.microsoft.authorize_redirect(request, redirect_uri)


@router.get("/callback")
async def auth_callback(request: Request):
    """
    Handles the callback from Microsoft after successful login.
    Exchanges the authorization code for an access token and user info.
    """
    try:
        token = await oauth.microsoft.authorize_access_token(request)
        user = token.get('userinfo')
        
        if not user:
             # Sometimes userinfo is not directly in the token depending on claims, 
             # allow fetch via userinfo endpoint if configured, or parse id_token
             user = await oauth.microsoft.userinfo(token=token)

        # Store user info in session (cookie)
        # In a real app, you might issue your own JWT here instead
        request.session['user'] = dict(user)
        
        return {"message": "Login successful", "user": user}
    except Exception as e:
        # Log the error in production
        raise HTTPException(status_code=400, detail=f"SSO Login Failed: {str(e)}")


@router.get("/logout")
async def logout(request: Request):
    """
    Clears the local session.
    """
    request.session.pop('user', None)
    return {"message": "Logged out successfully"}