illustrative abstractions

0%

Exploring Flask Authentication Methods Part 2

Continued

Last time we talked about CSRF tokens. So what is CSRF?

Cross-Site Request Forgery

Well, Wikipedia has a brief explanation of how it works. In short,

Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf[1]) or XSRF, is a type of malicious exploit of a website where unauthorized commands are transmitted from a user that the web application trusts.

There are many ways to utilise CSRF on unprotected websites. However, this can be largely prevented by providing the user with a csrf_token only when they logging in on the valid website, and storing them in sessions.

Solution

My final solution to this problem, in the Swift code below, is to use a web request to get a csrf_token and then login with a valid user request.

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
static func fetchCSRFToken () -> String {
var csrfToken = ""
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: URL.init(string: newAdapter.generateLoginQueryURL())!) {(data, response, error) in
defer { semaphore.signal() }
guard let data = data else { return }
do {
let divFields: Elements = try SwiftSoup.parse(String(decoding: data, as: UTF8.self)).body()!.select("div")
let centreDiv = divFields.array()[1]
let inputFields = try centreDiv.select("form").first()!.select("input")
for inputField in inputFields {
if inputField.id() == "csrf_token" {
csrfToken = try inputField.val()
}
}
} catch {
print("error: cannot fetch csrf token")
}
}
task.resume()
semaphore.wait()
if (csrfToken == "") {
fatalError("error: cannot fetch csrf token")
} else {
return csrfToken
}
}

Afterwards, generate a POST request in JSON style (e.g. {email: "[email protected]", password:"pwd", csrf_token:"token"}) and post it to your designated flask-security login endpoint. You will get a response with your authentication token. From then on, use this authentication token for future requests.

What’s more?

Authentication tokens should have a valid lifetime and re-authenticate from time to time to ensure better security. We have yet to come up with a solution to modify flask-security‘s internal mechanisms to realise this feature.

Regarding the HTTP request, we are planning to adapt to Alamofire for more elegant network solutions.

More

For more information, checkout

  • Wikipedia - Cross-site Request Forgery
  • CSRF Protection - Flask