1- from flask import Flask , render_template , request , session , redirect
1+ from flask import Flask , render_template , request , session , redirect , make_response
22import os , sys
33import requests
44import jwt
5+ import uuid
56
67CLIENT_ID = 'valtech.idp.testclient.local'
78CLIENT_SECRET = os .environ .get ('CLIENT_SECRET' )
@@ -27,12 +28,27 @@ def index():
2728@app .route ('/sign-in' )
2829def sign_in ():
2930 if session .get ('signed_in' ) != None : return redirect ('/' )
30- authorize_url = 'https://stage-id.valtech.com/oauth2/authorize?response_type=%s&client_id=%s&scope=%s' % ('code' , CLIENT_ID , 'email openid' )
31- return redirect (authorize_url )
31+
32+ # state is used for CSRF protection. the client generates a value and stores it
33+ # for the user somewhere (in a cookie or in a session). it then passes the same value
34+ # in the state parameter in the authorize request. IDP will mirror the state value
35+ # to the redirect URI. the client should then make sure the state value it has stored
36+ # matches what it receives in the callback
37+ state = str (uuid .uuid4 ())
38+
39+ authorize_url = 'https://stage-id.valtech.com/oauth2/authorize?response_type=%s&client_id=%s&scope=%s&state=%s' % ('code' , CLIENT_ID , 'email openid' , state )
40+
41+ resp = make_response (redirect (authorize_url ))
42+ resp .set_cookie ('python-flask-csrf' , state )
43+ return resp
3244
3345@app .route ('/sign-in/callback' )
3446def sign_in_callback ():
3547 code = request .args .get ('code' )
48+ state = request .args .get ('state' )
49+
50+ if state != request .cookies .get ('python-flask-csrf' ):
51+ raise Exception ("Possible CSRF detected (state does not match stored state)" )
3652
3753 # as both scope openid and email was requested on authorize request above, the client
3854 # will receive both an access_token (according to OAuth 2) AND an id_token (according to OpenID Connect)
@@ -49,8 +65,10 @@ def sign_in_callback():
4965
5066 session ['signed_in' ] = True
5167 session ['email' ] = user_info ['email' ]
52-
53- return redirect ('/' )
68+
69+ resp = make_response (redirect ('/' ))
70+ resp .set_cookie ('python-flask-csrf' , '' , expires = 0 )
71+ return resp
5472
5573@app .route ('/sign-out' )
5674def sign_out ():
0 commit comments