Coverage for heritrace/routes/auth.py: 100%

46 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-18 11:10 +0000

1import os 

2from datetime import timedelta 

3 

4from flask import Blueprint, current_app, flash, redirect, request, session, url_for 

5from flask_babel import gettext 

6from flask_login import current_user, login_required, login_user, logout_user 

7from heritrace.models import User 

8from requests_oauthlib import OAuth2Session 

9 

10auth_bp = Blueprint("auth", __name__) 

11 

12 

13@auth_bp.route("/login") 

14def login(): 

15 if current_user.is_authenticated: 

16 return redirect(url_for("main.catalogue")) 

17 

18 callback_url = url_for("auth.callback", _external=True, _scheme="https") 

19 orcid = OAuth2Session( 

20 current_app.config["ORCID_CLIENT_ID"], 

21 redirect_uri=callback_url, 

22 scope=[current_app.config["ORCID_SCOPE"], "openid"], 

23 ) 

24 authorization_url, state = orcid.authorization_url( 

25 current_app.config["ORCID_AUTHORIZE_URL"], 

26 prompt="login", # Forza il re-login 

27 nonce=os.urandom(16).hex(), # Aggiungiamo un nonce per sicurezza 

28 ) 

29 session["oauth_state"] = state 

30 return redirect(authorization_url) 

31 

32 

33@auth_bp.route("/callback") 

34def callback(): 

35 if request.url.startswith("http://"): 

36 secure_url = request.url.replace("http://", "https://", 1) 

37 else: 

38 secure_url = request.url 

39 

40 orcid = OAuth2Session( 

41 current_app.config["ORCID_CLIENT_ID"], state=session["oauth_state"] 

42 ) 

43 try: 

44 token = orcid.fetch_token( 

45 current_app.config["ORCID_TOKEN_URL"], 

46 client_secret=current_app.config["ORCID_CLIENT_SECRET"], 

47 authorization_response=secure_url, 

48 ) 

49 except Exception as e: 

50 flash( 

51 gettext("An error occurred during authentication. Please try again"), 

52 "danger", 

53 ) 

54 return redirect(url_for("auth.login")) 

55 orcid_id = token["orcid"] 

56 

57 if orcid_id not in current_app.config["ORCID_WHITELIST"]: 

58 flash( 

59 gettext("Your ORCID is not authorized to access this application"), "danger" 

60 ) 

61 return redirect(url_for("auth.login")) 

62 session["user_name"] = token["name"] 

63 user = User(id=orcid_id, name=token["name"], orcid=orcid_id) 

64 session.permanent = True 

65 current_app.permanent_session_lifetime = timedelta(days=30) 

66 login_user(user) 

67 flash(gettext("Welcome back %(name)s!", name=current_user.name), "success") 

68 return redirect(url_for("main.catalogue")) 

69 

70 

71@auth_bp.route("/logout") 

72def logout(): 

73 if not current_user.is_authenticated: 

74 return "", 401 

75 logout_user() 

76 flash(gettext("You have been logged out"), "info") 

77 return redirect(url_for("main.index"))