token.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from flask import request, jsonify
  2. from app.extensions import db
  3. from app.jose_utils import make_id_token
  4. from app.log import LOG
  5. from app.models import Client, AuthorizationCode, OauthToken, ClientUser
  6. from app.oauth.base import oauth_bp
  7. from app.oauth.views.authorize import generate_access_token
  8. from app.oauth_models import ScopeE
  9. @oauth_bp.route("/token", methods=["POST"])
  10. def get_access_token():
  11. """
  12. Calls by client to exchange the access token given the authorization code.
  13. The client authentications using Basic Authentication.
  14. The form contains the following data:
  15. - grant_type: must be "authorization_code"
  16. - code: the code obtained in previous step
  17. """
  18. # Basic authentication
  19. oauth_client_id = (
  20. request.authorization and request.authorization.username
  21. ) or request.form.get("client_id")
  22. oauth_client_secret = (
  23. request.authorization and request.authorization.password
  24. ) or request.form.get("client_secret")
  25. client = Client.filter_by(
  26. oauth_client_id=oauth_client_id, oauth_client_secret=oauth_client_secret
  27. ).first()
  28. if not client:
  29. return jsonify(error="wrong client-id or client-secret"), 400
  30. # Get code from form data
  31. grant_type = request.form.get("grant_type")
  32. code = request.form.get("code")
  33. # sanity check
  34. if grant_type != "authorization_code":
  35. return jsonify(error="grant_type must be authorization_code"), 400
  36. auth_code: AuthorizationCode = AuthorizationCode.filter_by(code=code).first()
  37. if not auth_code:
  38. return jsonify(error=f"no such authorization code {code}"), 400
  39. if auth_code.client_id != client.id:
  40. return jsonify(error=f"are you sure this code belongs to you?"), 400
  41. LOG.debug(
  42. "Create Oauth token for user %s, client %s", auth_code.user, auth_code.client
  43. )
  44. # Create token
  45. oauth_token = OauthToken.create(
  46. client_id=auth_code.client_id,
  47. user_id=auth_code.user_id,
  48. scope=auth_code.scope,
  49. redirect_uri=auth_code.redirect_uri,
  50. access_token=generate_access_token(),
  51. )
  52. db.session.add(oauth_token)
  53. # Auth code can be used only once
  54. db.session.delete(auth_code)
  55. db.session.commit()
  56. client_user: ClientUser = ClientUser.get_by(
  57. client_id=auth_code.client_id, user_id=auth_code.user_id
  58. )
  59. user_data = client_user.get_user_info()
  60. res = {
  61. "access_token": oauth_token.access_token,
  62. "token_type": "bearer",
  63. "expires_in": 3600,
  64. "scope": "",
  65. "user": user_data,
  66. }
  67. if oauth_token.scope and ScopeE.OPENID.value in oauth_token.scope:
  68. res["id_token"] = make_id_token(client_user)
  69. return jsonify(res)