@@ -97,7 +97,7 @@ def set_login_cookie(cls, handler, user_id=None):
97
97
auth_header_pat = re .compile ('token\s+(.+)' , re .IGNORECASE )
98
98
99
99
@classmethod
100
- def get_user_token (cls , handler ):
100
+ def get_token (cls , handler ):
101
101
"""Get the user token from a request
102
102
103
103
Default:
@@ -120,11 +120,22 @@ def should_check_origin(cls, handler):
120
120
121
121
Origin check should be skipped for token-authenticated requests.
122
122
"""
123
+ return not cls .is_token_authenticated (handler )
124
+
125
+ @classmethod
126
+ def is_token_authenticated (cls , handler ):
127
+ """Check if the handler has been authenticated by a token.
128
+
129
+ This is used to signal certain things, such as:
130
+
131
+ - permit access to REST API
132
+ - xsrf protection
133
+ - skip origin-checks for scripts
134
+ """
123
135
if getattr (handler , '_user_id' , None ) is None :
124
136
# ensure get_user has been called, so we know if we're token-authenticated
125
137
handler .get_current_user ()
126
- token_authenticated = getattr (handler , '_token_authenticated' , False )
127
- return not token_authenticated
138
+ return getattr (handler , '_token_authenticated' , False )
128
139
129
140
@classmethod
130
141
def get_user (cls , handler ):
@@ -136,40 +147,51 @@ def get_user(cls, handler):
136
147
# called on LoginHandler itself.
137
148
if getattr (handler , '_user_id' , None ):
138
149
return handler ._user_id
139
- user_id = handler .get_secure_cookie (handler .cookie_name )
140
- if not user_id :
150
+ user_id = cls .get_user_token (handler )
151
+ if user_id is None :
152
+ user_id = handler .get_secure_cookie (handler .cookie_name )
153
+ else :
154
+ cls .set_login_cookie (handler , user_id )
155
+ # Record that we've been authenticated with a token.
156
+ # Used in should_check_origin above.
157
+ handler ._token_authenticated = True
158
+ if user_id is None :
141
159
# prevent extra Invalid cookie sig warnings:
142
160
handler .clear_login_cookie ()
143
- token = handler .token
144
- if not token and not handler .login_available :
161
+ if not handler .login_available :
145
162
# Completely insecure! No authentication at all.
146
163
# No need to warn here, though; validate_security will have already done that.
147
- return 'anonymous'
148
- if token :
149
- # check login token from URL argument or Authorization header
150
- user_token = cls .get_user_token (handler )
151
- one_time_token = handler .one_time_token
152
- authenticated = False
153
- if user_token == token :
154
- # token-authenticated, set the login cookie
155
- handler .log .info ("Accepting token-authenticated connection from %s" , handler .request .remote_ip )
156
- authenticated = True
157
- elif one_time_token and user_token == one_time_token :
158
- # one-time-token-authenticated, only allow this token once
159
- handler .settings .pop ('one_time_token' , None )
160
- handler .log .info ("Accepting one-time-token-authenticated connection from %s" , handler .request .remote_ip )
161
- authenticated = True
162
- if authenticated :
163
- user_id = uuid .uuid4 ().hex
164
- cls .set_login_cookie (handler , user_id )
165
- # Record that we've been authenticated with a token.
166
- # Used in should_check_origin above.
167
- handler ._token_authenticated = True
164
+ user_id = 'anonymous'
168
165
169
166
# cache value for future retrievals on the same request
170
167
handler ._user_id = user_id
171
168
return user_id
172
169
170
+ @classmethod
171
+ def get_user_token (cls , handler ):
172
+ """Identify the user based on a token in the URL or Authorization header"""
173
+ token = handler .token
174
+ if not token :
175
+ return
176
+ # check login token from URL argument or Authorization header
177
+ user_token = cls .get_token (handler )
178
+ one_time_token = handler .one_time_token
179
+ authenticated = False
180
+ if user_token == token :
181
+ # token-authenticated, set the login cookie
182
+ handler .log .debug ("Accepting token-authenticated connection from %s" , handler .request .remote_ip )
183
+ authenticated = True
184
+ elif one_time_token and user_token == one_time_token :
185
+ # one-time-token-authenticated, only allow this token once
186
+ handler .settings .pop ('one_time_token' , None )
187
+ handler .log .info ("Accepting one-time-token-authenticated connection from %s" , handler .request .remote_ip )
188
+ authenticated = True
189
+
190
+ if authenticated :
191
+ return uuid .uuid4 ().hex
192
+ else :
193
+ return None
194
+
173
195
174
196
@classmethod
175
197
def validate_security (cls , app , ssl_options = None ):
0 commit comments