Browse Source

feat(auth): use base64 encoded tokens

Using base64 rather than hex notation for tokens saves some length
in their ASCII (utf-8) representation, without weakening security.
This commit in fact increases security by 8 bit, using 21 random
bytes for tokens rather than 20 bytes (this is due to some padding
in base64, so 20 bytes and 21 bytes will both be represented by
28 chars in base64).

Old tokens in hex representation will remain vaild.
Nils Wisiol 6 năm trước cách đây
mục cha
commit
d068c2aa85
4 tập tin đã thay đổi với 13 bổ sung5 xóa
  1. 5 0
      api/desecapi/models.py
  2. 2 0
      test/e2e/schemas.js
  3. 4 4
      test/e2e/spec/api_spec.js
  4. 2 1
      test/e2e/spec/dyndns_spec.js

+ 5 - 0
api/desecapi/models.py

@@ -9,6 +9,8 @@ from django.core.validators import MinValueValidator
 from collections import OrderedDict
 import rest_framework.authtoken.models
 from time import time
+from os import urandom
+from base64 import b64encode
 
 
 class MyUserManager(BaseUserManager):
@@ -59,6 +61,9 @@ class Token(rest_framework.authtoken.models.Token):
             self.user_specific_id = int(time() * 100000)
         super().save(*args, **kwargs) # Call the "real" save() method.
 
+    def generate_key(self):
+        return b64encode(urandom(21)).decode('utf-8')
+
     class Meta:
         abstract = False
         unique_together = (('user', 'user_specific_id'),)

+ 2 - 0
test/e2e/schemas.js

@@ -60,3 +60,5 @@ exports.tokens = {
     type: "array",
     items: exports.token
 };
+
+exports.TOKEN_REGEX = /^[A-Za-z0-9+/]{28}$/

+ 4 - 4
test/e2e/spec/api_spec.js

@@ -64,7 +64,7 @@ describe("API", function () {
                 "email": email,
                 "password": password,
             }).then(function (loginResponse) {
-                expect(loginResponse.body.auth_token).to.match(/^[a-z0-9]{40}$/);
+                expect(loginResponse.body.auth_token).to.match(schemas.TOKEN_REGEX);
                 token = loginResponse.body.auth_token;
             });
         });
@@ -80,7 +80,7 @@ describe("API", function () {
                         "password": password,
                     }).then(function (loginResponse) {
                         expect(loginResponse).to.have.status(201);
-                        expect(loginResponse.body.auth_token).to.match(/^[a-z0-9]{40}$/);
+                        expect(loginResponse.body.auth_token).to.match(schemas.TOKEN_REGEX);
                         token1 = loginResponse.body.auth_token;
                         expect(token1).to.not.equal(token2);
                     }),
@@ -89,7 +89,7 @@ describe("API", function () {
                         "password": password,
                     }).then(function (loginResponse) {
                         expect(loginResponse).to.have.status(201);
-                        expect(loginResponse.body.auth_token).to.match(/^[a-z0-9]{40}$/);
+                        expect(loginResponse.body.auth_token).to.match(schemas.TOKEN_REGEX);
                         token2 = loginResponse.body.auth_token;
                         expect(token2).to.not.equal(token1);
                     })
@@ -180,7 +180,7 @@ describe("API", function () {
                     "email": email,
                     "password": password,
                 }).then(function (loginResponse) {
-                    expect(loginResponse.body.auth_token).to.match(/^[a-z0-9]{40}$/);
+                    expect(loginResponse.body.auth_token).to.match(schemas.TOKEN_REGEX);
                     token = loginResponse.body.auth_token;
                     chakram.setRequestHeader('Authorization', 'Token ' + token);
                 });

+ 2 - 1
test/e2e/spec/dyndns_spec.js

@@ -1,6 +1,7 @@
 var chakram = require("./../setup.js").chakram;
 var expect = chakram.expect;
 var itShowsUpInPdnsAs = require("./../setup.js").itShowsUpInPdnsAs;
+var schemas = require("./../schemas.js");
 
 describe("dyndns service", function () {
 
@@ -31,7 +32,7 @@ describe("dyndns service", function () {
                     "email": email,
                     "password": password,
                 }).then(function (loginResponse) {
-                    expect(loginResponse.body.auth_token).to.match(/^[a-z0-9]{40}$/);
+                    expect(loginResponse.body.auth_token).to.match(schemas.TOKEN_REGEX);
                     token = loginResponse.body.auth_token;
                     chakram.setRequestHeader('Authorization', 'Token ' + token);
                 });