Skip to content
Snippets Groups Projects
Commit b8f2736b authored by Julian's avatar Julian
Browse files

Moved token generation to common module and introduced token_urlfriendly


Broken mail clients like Thunderbird fail to recognize urlsafe characters
like "-" as part of an URL. token_urlfriendly avoids those characters.

Closes #93.

Co-authored-by: default avatarnd <nd@cccv.de>
parent e48585cb
Branches
Tags
No related merge requests found
import secrets
import datetime import datetime
from flask import current_app from flask import current_app
...@@ -9,6 +8,7 @@ from uffd.ldapalchemy.dbutils import DBRelationship ...@@ -9,6 +8,7 @@ from uffd.ldapalchemy.dbutils import DBRelationship
from uffd.database import db from uffd.database import db
from uffd.user.models import User from uffd.user.models import User
from uffd.signup.models import Signup from uffd.signup.models import Signup
from uffd.utils import token_urlfriendly
invite_roles = db.Table('invite_roles', invite_roles = db.Table('invite_roles',
Column('invite_id', Integer(), ForeignKey('invite.id'), primary_key=True), Column('invite_id', Integer(), ForeignKey('invite.id'), primary_key=True),
...@@ -18,7 +18,7 @@ invite_roles = db.Table('invite_roles', ...@@ -18,7 +18,7 @@ invite_roles = db.Table('invite_roles',
class Invite(db.Model): class Invite(db.Model):
__tablename__ = 'invite' __tablename__ = 'invite'
id = Column(Integer(), primary_key=True, autoincrement=True) id = Column(Integer(), primary_key=True, autoincrement=True)
token = Column(String(128), unique=True, nullable=False, default=lambda: secrets.token_urlsafe(48)) token = Column(String(128), unique=True, nullable=False, default=token_urlfriendly)
created = Column(DateTime, default=datetime.datetime.now, nullable=False) created = Column(DateTime, default=datetime.datetime.now, nullable=False)
creator_dn = Column(String(128), nullable=True) creator_dn = Column(String(128), nullable=True)
creator = DBRelationship('creator_dn', User) creator = DBRelationship('creator_dn', User)
......
import datetime import datetime
import secrets
from sqlalchemy import Column, String, DateTime from sqlalchemy import Column, String, DateTime
from uffd.database import db from uffd.database import db
from uffd.utils import token_urlfriendly
def random_token():
return secrets.token_hex(128)
class Token(): class Token():
token = Column(String(128), primary_key=True, default=random_token) token = Column(String(128), primary_key=True, default=token_urlfriendly)
created = Column(DateTime, default=datetime.datetime.now) created = Column(DateTime, default=datetime.datetime.now)
class PasswordToken(Token, db.Model): class PasswordToken(Token, db.Model):
......
import datetime import datetime
import secrets import secrets
import math
import enum import enum
from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum
...@@ -10,15 +9,7 @@ from sqlalchemy.ext.hybrid import hybrid_property ...@@ -10,15 +9,7 @@ from sqlalchemy.ext.hybrid import hybrid_property
from uffd.ldapalchemy.dbutils import DBRelationship from uffd.ldapalchemy.dbutils import DBRelationship
from uffd.database import db from uffd.database import db
from uffd.user.models import User from uffd.user.models import User
from uffd.utils import token_typeable
def token_typeable(nbytes=None):
'''Return random text token that is easy to type (on mobile)'''
alphabet = '123456789abcdefghkmnopqrstuvwx' # No '0ijlyz'
if nbytes is None:
nbytes = secrets.DEFAULT_ENTROPY
nbytes_per_char = math.log(len(alphabet), 256)
nchars = math.ceil(nbytes / nbytes_per_char)
return ''.join([secrets.choice(alphabet) for _ in range(nchars)])
# Device login provides a convenient and secure way to log into SSO-enabled # Device login provides a convenient and secure way to log into SSO-enabled
# services on a secondary device without entering the user password or # services on a secondary device without entering the user password or
......
import secrets
import datetime import datetime
from crypt import crypt from crypt import crypt
...@@ -8,6 +7,7 @@ from uffd.ldapalchemy.dbutils import DBRelationship ...@@ -8,6 +7,7 @@ from uffd.ldapalchemy.dbutils import DBRelationship
from uffd.database import db from uffd.database import db
from uffd.ldap import ldap from uffd.ldap import ldap
from uffd.user.models import User from uffd.user.models import User
from uffd.utils import token_urlfriendly
class Signup(db.Model): class Signup(db.Model):
'''Model that represents a self-signup request '''Model that represents a self-signup request
...@@ -26,7 +26,7 @@ class Signup(db.Model): ...@@ -26,7 +26,7 @@ class Signup(db.Model):
As long as they are not completed, signup requests have no effect each other As long as they are not completed, signup requests have no effect each other
or different parts of the application.''' or different parts of the application.'''
__tablename__ = 'signup' __tablename__ = 'signup'
token = Column(String(128), primary_key=True, default=lambda: secrets.token_urlsafe(48)) token = Column(String(128), primary_key=True, default=token_urlfriendly)
created = Column(DateTime, default=datetime.datetime.now, nullable=False) created = Column(DateTime, default=datetime.datetime.now, nullable=False)
loginname = Column(Text) loginname = Column(Text)
displayname = Column(Text) displayname = Column(Text)
......
import secrets
import math
def token_with_alphabet(alphabet, nbytes=None):
'''Return random text token that consists of characters from `alphabet`'''
if nbytes is None:
nbytes = max(secrets.DEFAULT_ENTROPY, 32)
nbytes_per_char = math.log(len(alphabet), 256)
nchars = math.ceil(nbytes / nbytes_per_char)
return ''.join([secrets.choice(alphabet) for _ in range(nchars)])
def token_typeable(nbytes=None):
'''Return random text token that is easy to type (on mobile)'''
alphabet = '123456789abcdefghkmnopqrstuvwx' # No '0ijlyz'
return token_with_alphabet(alphabet, nbytes=nbytes)
def token_urlfriendly(nbytes=None):
'''Return random text token that is urlsafe and works around common parsing bugs'''
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
return token_with_alphabet(alphabet, nbytes=nbytes)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment