コード例 #1
0
ファイル: views.py プロジェクト: Eratosthenes/adsws
    def bootstrap_user_new(self, client_name=None, scopes=None, ratelimit=1.0):
        """
        Create a OAuthClient owned by the authenticated real user.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email != current_app.config['BOOTSTRAP_USER_EMAIL']
        self._check_ratelimit(ratelimit)

        uid = current_user.get_id()
        client_name = client_name or current_app.config.get(
            'BOOTSTRAP_CLIENT_NAME', 'BB client')

        client = OAuthClient(
            user_id=current_user.get_id(),
            name=client_name,
            description=client_name,
            is_confidential=True,
            is_internal=True,
            _default_scopes=scopes
            or ' '.join(current_app.config['USER_DEFAULT_SCOPES']),
            ratelimit=ratelimit)
        client.gen_salt()
        db.session.add(client)

        token = Bootstrap.create_user_token(client)
        db.session.add(token)
        current_app.logger.info("Created OAuth client for {email}".format(
            email=current_user.email))
        db.session.commit()
        return client, token
コード例 #2
0
ファイル: views.py プロジェクト: Eratosthenes/adsws
    def bootstrap_bumblebee():
        """
        Return or create a OAuthClient owned by the "bumblebee" user.
        Re-uses an existing client if "oauth_client" is encoded into the
        session cookie, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email == current_app.config['BOOTSTRAP_USER_EMAIL']

        client_name = current_app.config.get('BOOTSTRAP_CLIENT_NAME',
                                             'BB client')
        scopes = ' '.join(current_app.config.get('BOOTSTRAP_SCOPES', []))

        client = OAuthClient(user_id=current_user.get_id(),
                             name=client_name,
                             description=client_name,
                             is_confidential=False,
                             is_internal=True,
                             _default_scopes=scopes,
                             ratelimit=1.0)
        client.gen_salt()

        db.session.add(client)

        token = Bootstrap.create_temporary_token(client)

        db.session.add(token)
        db.session.commit()
        return client, token
コード例 #3
0
ファイル: views.py プロジェクト: aaccomazzi/adsws
    def bootstrap_user(self,
                       client_name=None,
                       scopes=None,
                       ratelimit=1.0,
                       expires=datetime.datetime(2500, 1, 1)):
        """
        Return or create a OAuthClient owned by the authenticated real user.
        Re-uses an existing client if "oauth_client" is found in the database
        for this user, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email != current_app.config['BOOTSTRAP_USER_EMAIL']

        uid = current_user.get_id()
        client_name = client_name or current_app.config.get(
            'BOOTSTRAP_CLIENT_NAME', 'BB client')

        client = OAuthClient.query.filter_by(
            user_id=uid,
            name=client_name,
        ).order_by(OAuthClient.created.desc()).first()

        if client is None:
            self._check_ratelimit(ratelimit)
            client = OAuthClient(
                user_id=current_user.get_id(),
                name=client_name,
                description=client_name,
                is_confidential=True,
                is_internal=True,
                _default_scopes=scopes
                or ' '.join(current_app.config['USER_DEFAULT_SCOPES']),
                ratelimit=ratelimit)
            client.gen_salt()
            db.session.add(client)

            token = Bootstrap.create_user_token(client, expires=expires)
            db.session.add(token)
            current_app.logger.info("Created BB client for {email}".format(
                email=current_user.email))
        else:
            token = OAuthToken.query.filter_by(
                client_id=client.client_id,
                user_id=current_user.get_id(),
            ).first()

            if token is None:
                # the token was not created yet
                token = Bootstrap.create_user_token(client, expires=expires)

                db.session.add(token)
                current_app.logger.info("Created BB client for {email}".format(
                    email=current_user.email))

        db.session.commit()
        return client, token
コード例 #4
0
ファイル: views.py プロジェクト: jonnybazookatone/adsws
    def bootstrap_user():
        """
        Return or create a OAuthClient owned by the authenticated real user.
        Re-uses an existing client if "oauth_client" is found in the database
        for this user, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email != current_app.config['BOOTSTRAP_USER_EMAIL']

        uid = current_user.get_id()
        client_name = current_app.config.get('BOOTSTRAP_CLIENT_NAME', 'BB client')

        client = OAuthClient.query.filter_by(
            user_id=uid,
            name=client_name,
        ).first()

        if client is None:
            scopes = ' '.join(current_app.config['USER_DEFAULT_SCOPES'])
            salt_length = current_app.config.get('OAUTH2_CLIENT_ID_SALT_LEN', 40)
            client = OAuthClient(
                user_id=current_user.get_id(),
                name=client_name,
                description=client_name,
                is_confidential=True,
                is_internal=True,
                _default_scopes=scopes,
            )
            client.gen_salt()
            db.session.add(client)

            token = OAuthToken(
                client_id=client.client_id,
                user_id=uid,
                access_token=gen_salt(salt_length),
                refresh_token=gen_salt(salt_length),
                expires=datetime.datetime(2500, 1, 1),
                _scopes=scopes,
                is_personal=False,
                is_internal=True,
            )
            db.session.add(token)
            db.session.commit()
            current_app.logger.info(
                "Created BB client for {email}".format(email=current_user.email)
            )
        else:
            token = OAuthToken.query.filter_by(
                client_id=client.client_id,
                user_id=current_user.get_id(),
            ).first()

        return client, token
コード例 #5
0
    def bootstrap_bumblebee():
        """
        Return or create a OAuthClient owned by the "bumblebee" user.
        Re-uses an existing client if "oauth_client" is encoded into the
        session cookie, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email == current_app.config['BOOTSTRAP_USER_EMAIL']

        salt_length = current_app.config.get('OAUTH2_CLIENT_ID_SALT_LEN', 40)
        scopes = ' '.join(current_app.config.get('BOOTSTRAP_SCOPES', []))
        expires = current_app.config.get('BOOTSTRAP_TOKEN_EXPIRES', 3600 * 24)
        client_name = current_app.config.get('BOOTSTRAP_CLIENT_NAME',
                                             'BB client')
        uid = current_user.get_id()

        client = OAuthClient(
            user_id=uid,
            name=client_name,
            description=client_name,
            is_confidential=False,
            is_internal=True,
            _default_scopes=scopes,
        )
        client.gen_salt()

        db.session.add(client)

        if isinstance(expires, int):
            expires = datetime.datetime.utcnow() + datetime.timedelta(
                seconds=expires)

        token = OAuthToken(
            client_id=client.client_id,
            user_id=uid,
            expires=expires,
            _scopes=scopes,
            access_token=gen_salt(salt_length),
            refresh_token=gen_salt(salt_length),
            is_personal=False,
            is_internal=True,
        )

        db.session.add(token)
        db.session.commit()
        return client, token
コード例 #6
0
    def put(self):
        """
        Generates a new API key
        :return: dict containing the API key data structure
        """

        client = OAuthClient.query.filter_by(
            user_id=current_user.get_id(),
            name=u'ADS API client',
        ).first()

        if client is None:  # If no client exists, create a new one
            client = OAuthClient(
                user_id=current_user.get_id(),
                name=u'ADS API client',
                description=u'ADS API client',
                is_confidential=False,
                is_internal=True,
                _default_scopes=' '.join(
                    current_app.config['USER_API_DEFAULT_SCOPES']
                ),
                ratelimit=1.0
            )
            client.gen_salt()

            token = OAuthToken(
                client_id=client.client_id,
                user_id=current_user.get_id(),
                access_token=gen_salt(40),
                refresh_token=gen_salt(40),
                expires=datetime.datetime(2500, 1, 1),
                _scopes=' '.join(
                    current_app.config['USER_API_DEFAULT_SCOPES']
                ),
                is_personal=False,
            )

            db.session.add(client)
            db.session.add(token)
            try:
                db.session.commit()
            except Exception, e:
                current_app.logger.error("Unknown DB error: {0}".format(e))
                abort(503)
            current_app.logger.info(
                "Created ADS API client+token for {0}".format(
                    current_user.email
                )
            )
コード例 #7
0
ファイル: views.py プロジェクト: romanchyla/adsws
    def bootstrap_bumblebee():
        """
        Return or create a OAuthClient owned by the "bumblebee" user.
        Re-uses an existing client if "oauth_client" is encoded into the
        session cookie, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email == current_app.config['BOOTSTRAP_USER_EMAIL']

        salt_length = current_app.config.get('OAUTH2_CLIENT_ID_SALT_LEN', 40)
        scopes = ' '.join(current_app.config.get('BOOTSTRAP_SCOPES', []))
        expires = current_app.config.get('BOOTSTRAP_TOKEN_EXPIRES', 3600*24)
        client_name = current_app.config.get('BOOTSTRAP_CLIENT_NAME', 'BB client')
        uid = current_user.get_id()

        client = OAuthClient(
            user_id=uid,
            name=client_name,
            description=client_name,
            is_confidential=False,
            is_internal=True,
            _default_scopes=scopes,
        )
        client.gen_salt()

        db.session.add(client)

        if isinstance(expires, int):
            expires = datetime.datetime.utcnow() + datetime.timedelta(
                seconds=expires)

        token = OAuthToken(
            client_id=client.client_id,
            user_id=uid,
            expires=expires,
            _scopes=scopes,
            access_token=gen_salt(salt_length),
            refresh_token=gen_salt(salt_length),
            is_personal=False,
            is_internal=True,
        )

        db.session.add(token)
        db.session.commit()
        return client, token
コード例 #8
0
ファイル: views.py プロジェクト: romanchyla/adsws
    def put(self):
        """
        Generates a new API key
        :return: dict containing the API key data structure
        """

        client = OAuthClient.query.filter_by(
            user_id=current_user.get_id(),
            name=u'ADS API client',
        ).first()

        if client is None:  # If no client exists, create a new one
            client = OAuthClient(
                user_id=current_user.get_id(),
                name=u'ADS API client',
                description=u'ADS API client',
                is_confidential=False,
                is_internal=True,
                _default_scopes=' '.join(
                    current_app.config['USER_API_DEFAULT_SCOPES']
                ),
            )
            client.gen_salt()

            token = OAuthToken(
                client_id=client.client_id,
                user_id=current_user.get_id(),
                access_token=gen_salt(40),
                refresh_token=gen_salt(40),
                expires=datetime.datetime(2500, 1, 1),
                _scopes=' '.join(
                    current_app.config['USER_API_DEFAULT_SCOPES']
                ),
                is_personal=False,
            )

            db.session.add(client)
            db.session.add(token)
            try:
                db.session.commit()
            except Exception, e:
                current_app.logger.error("Unknown DB error: {0}".format(e))
                abort(503)
            current_app.logger.info(
                "Created ADS API client+token for {0}".format(
                    current_user.email
                )
            )
コード例 #9
0
ファイル: test_commands.py プロジェクト: spacemansteve/adsws
 def _create_client(self, client_id='test', user_id=0, scopes='adsws:internal'):
     # create a client in the database
     c1 = OAuthClient(
         client_id=client_id,
         client_secret='client secret %s' % random.random(),
         name='bumblebee',
         description='',
         is_confidential=False,
         user_id=user_id,
         _redirect_uris='%s/client/authorized' % self.app.config.get('SITE_SECURE_URL'),
         _default_scopes=scopes
     )
     db.session.add(c1)
     db.session.commit()
     return OAuthClient.query.filter_by(client_secret=c1.client_secret).one()
コード例 #10
0
ファイル: api_base.py プロジェクト: spacemansteve/adsws
    def setUp(self):
        @self.app.route('/postlogin')
        def username():
            if current_user.is_authenticated():
                return current_user.email
            return u'Anonymous'

        @self.app.errorhandler(404)
        def handle_404(e):
            raise e
        db.create_all(app=self.app)

        FlaskAppTestCase.setUp(self)

        user = user_manipulator.create(email='montysolr', password='******', active=True)
        self.user = user

        from adsws.modules.oauth2server.models import OAuthClient, Scope, OAuthToken
        from adsws.modules.oauth2server.registry import scopes as scopes_registry

        # Register a test scope
        scopes_registry.register(Scope('adsws:internal'))
        self.base_url = self.app.config.get('SITE_SECURE_URL')

        # create a client in the database
        c1 = OAuthClient(
            client_id='bumblebee',
            client_secret='client secret',
            name='bumblebee',
            description='',
            is_confidential=False,
            user_id=user.id,
            _redirect_uris='%s/client/authorized' % self.base_url,
            _default_scopes="adsws:internal",
            ratelimit=1.0
        )
        db.session.add(c1)
        db.session.commit()

        self.oauth = OAuth(self.app)

        # have the remote app ready
        self.authenticate()
コード例 #11
0
    def bootstrap_user():
        """
        Return or create a OAuthClient owned by the authenticated real user.
        Re-uses an existing client if "oauth_client" is found in the database
        for this user, otherwise writes a new client to the database.

        Similar logic performed for the OAuthToken.

        :return: OAuthToken instance
        """
        assert current_user.email != current_app.config['BOOTSTRAP_USER_EMAIL']

        uid = current_user.get_id()
        client_name = current_app.config.get('BOOTSTRAP_CLIENT_NAME',
                                             'BB client')

        client = OAuthClient.query.filter_by(
            user_id=uid,
            name=client_name,
        ).first()

        scopes = ' '.join(current_app.config['USER_DEFAULT_SCOPES'])
        salt_length = current_app.config.get('OAUTH2_CLIENT_ID_SALT_LEN', 40)

        if client is None:
            client = OAuthClient(
                user_id=current_user.get_id(),
                name=client_name,
                description=client_name,
                is_confidential=True,
                is_internal=True,
                _default_scopes=scopes,
            )
            client.gen_salt()
            db.session.add(client)

            token = OAuthToken(
                client_id=client.client_id,
                user_id=uid,
                access_token=gen_salt(salt_length),
                refresh_token=gen_salt(salt_length),
                expires=datetime.datetime(2500, 1, 1),
                _scopes=scopes,
                is_personal=False,
                is_internal=True,
            )
            db.session.add(token)
            current_app.logger.info("Created BB client for {email}".format(
                email=current_user.email))
        else:
            token = OAuthToken.query.filter_by(
                client_id=client.client_id,
                user_id=current_user.get_id(),
            ).first()

            if token is None:
                # the token was not created yet
                token = OAuthToken(
                    client_id=client.client_id,
                    user_id=uid,
                    access_token=gen_salt(salt_length),
                    refresh_token=gen_salt(salt_length),
                    expires=datetime.datetime(2500, 1, 1),
                    _scopes=scopes,
                    is_personal=False,
                    is_internal=True,
                )
                db.session.add(token)
                current_app.logger.info("Created BB client for {email}".format(
                    email=current_user.email))

        db.session.commit()
        return client, token
コード例 #12
0
def get_token():
  parser = argparse.ArgumentParser()
  add_arguments(parser)
  args = parser.parse_args()
  app = create_app('manual_client_registration',
    EXTENSIONS = ['adsws.ext.sqlalchemy',
                  'adsws.ext.security',],
    PACKAGES=['adsws.modules.oauth2server',])

  with app.app_context() as context:
    try:
      u = db.session.query(User).filter_by(email=args.user_email).one()
    except NoResultFound:
      if not args.create_user:
        sys.exit("User with email [%s] not found, and --create-user was not specified. Exiting." % args.user_email)
      u = User(email=args.user_email)
      db.session.add(u)
      db.session.commit()
    except MultipleResultsFound:
      raise DatabaseIntegrityError

    try:
      client = db.session.query(OAuthClient).filter_by(user_id=u.id,name=args.name).one()
    except MultipleResultsFound:
      raise DatabaseIntegrityError("Multiple oauthclients found for that user and name")
    except NoResultFound:
      client = OAuthClient(
        user_id = u.id,
        description=args.description,
        name=args.name,
        is_confidential=True,
        is_internal=True,)
      client.gen_salt()
      db.session.add(client)
      db.session.commit()

    try:
      tokens = db.session.query(OAuthToken).filter_by(
        client_id=client.client_id, 
        user_id=u.id, 
        is_personal=args.is_personal).all()
      #Iterate through each result and compare scopes
      matching_tokens = []
      for t in tokens:
        if set(args.scopes) == set(t.scopes):
          matching_tokens.append(t)
      if not matching_tokens:
        raise NoResultFound
      print "%s tokens with those definitions found, returning the first" % len(matching_tokens)
      token = matching_tokens[0]
    except NoResultFound:
      token = OAuthToken(
        client_id=client.client_id,
        user_id=u.id,
        access_token=gen_salt(current_app.config.get('OAUTH2_TOKEN_PERSONAL_SALT_LEN', 40)),
        refresh_token=gen_salt(current_app.config.get('OAUTH2_TOKEN_PERSONAL_SALT_LEN', 40)),
        _scopes=' '.join(args.scopes),
        expires=datetime.datetime(2050,1,1) if args.is_personal else None,
        is_personal=args.is_personal,
        is_internal=True,)
      db.session.add(token)
      db.session.commit()

    return {
      'access_token': token.access_token,
      'refresh_token': token.refresh_token,
      'username': u.email,
      'expires_in': token.expires.isoformat() if token.expires else None,
      'token_type': 'Bearer'}
コード例 #13
0
ファイル: test_commands.py プロジェクト: spacemansteve/adsws
    def test_cleanup_client(self):
        """
        Tests that oauth2clients whose last_activity attribute are properly
        removed from the database as a result of the cleanup_client procedure
        """
        original_clients = db.session.query(OAuthClient).all()
        self.assertEqual(5, len(original_clients))
        self.assertItemsEqual(
            filter(None, [i.last_activity for i in original_clients]),
            self.times,
        )

        # No clients should be cleaned
        cleanup_clients(app_override=self.app, timedelta="days=365")
        current_clients = db.session.query(OAuthClient).all()
        self.assertEqual(5, len(current_clients))

        # Cleanup all clients that are older than 0 seconds from now()
        cleanup_clients(app_override=self.app, timedelta="seconds=0")
        current_clients = db.session.query(OAuthClient).all()
        self.assertEqual(3, len(current_clients))

        # Wait 3 seconds, then perform the same cleanup. Should have one less
        # client after this operation.

        time.sleep(3.1)
        cleanup_clients(app_override=self.app, timedelta="seconds=0.1")
        current_clients = db.session.query(OAuthClient).all()
        self.assertEqual(2, len(current_clients))

        # Cleanup the client whose last_activity was set to 1 hour
        # into the future. This case should never happen in practice!
        cleanup_clients(app_override=self.app, timedelta="hours=-1")
        current_clients = db.session.query(OAuthClient).all()
        self.assertEqual(1, len(current_clients))

        # Only the client with last_activity=None should remain
        current_clients = db.session.query(OAuthClient).all()
        self.assertEqual(1, len(current_clients))
        self.assertIsNone(current_clients[0].last_activity)
        
        # test they can be cleaned up by userid
        db.session.add(OAuthClient(
            user_id=99,
            client_id=gen_salt(20),
            client_secret=gen_salt(20),
            is_confidential=False,
            is_internal=True,
            _default_scopes="",
            last_activity=datetime.datetime.now()
        ))
        db.session.add(OAuthClient(
            user_id=1,
            client_id=gen_salt(20),
            client_secret=gen_salt(20),
            is_confidential=False,
            is_internal=True,
            _default_scopes="",
            last_activity=datetime.datetime.now()
        ))
        db.session.commit()
        
        self.assertEqual(3, len(db.session.query(OAuthClient).all()))
        
        time.sleep(1.1)
        cleanup_clients(app_override=self.app, timedelta="seconds=0.1", userid=99)
        self.assertEqual(2, len(db.session.query(OAuthClient).all()))
        
        db.session.add(OAuthClient(
            user_id=99,
            client_id=gen_salt(20),
            client_secret=gen_salt(20),
            is_confidential=False,
            is_internal=True,
            _default_scopes="",
            last_activity=datetime.datetime.now(),
            ratelimit=0.2
        ))
        db.session.commit()
        time.sleep(0.5)
        
        cleanup_clients(app_override=self.app, timedelta="seconds=0.1", userid=99, ratelimit='0.19')
        self.assertEqual(3, len(db.session.query(OAuthClient).all()))
        
        cleanup_clients(app_override=self.app, timedelta="seconds=0.1", userid=99, ratelimit='0.2')
        self.assertEqual(2, len(db.session.query(OAuthClient).all()))
コード例 #14
0
ファイル: test_commands.py プロジェクト: spacemansteve/adsws
    def setUp(self):
        """
        Sets up all of the users, clients, and tokens that management commands
        will run against.
        """

        db.create_all(app=self.app)

        now = datetime.datetime.now()
        delta = datetime.timedelta
        times = [
            now,
            now-delta(seconds=3),
            now+delta(seconds=3),
            now+delta(hours=1),
        ]
        self.times = times  # Save for comparisons in the tests

        # This is a user that has registered but not confirmed their account
        u = user_manipulator.create(
            email="unconfirmed@unittest",
            registered_at=now+delta(seconds=1),
        )
        db.session.add(u)

        # This is a user that has registered but not confirmed their account,
        # and furthermore will not have a registered_at attribute set
        u = user_manipulator.create(
            email="blankuser@unittest",
        )
        db.session.add(u)

        # This is a user that has registered and confirmed their account
        u = user_manipulator.create(
            email="user@unittest",
            registered_at=now,
            confirmed_at=now,
        )
        db.session.add(u)

        for _time in times:

            client = OAuthClient(
                user_id=u.id,
                client_id=gen_salt(20),
                client_secret=gen_salt(20),
                is_confidential=False,
                is_internal=True,
                _default_scopes="",
                last_activity=_time,
            )
            db.session.add(client)

            token = OAuthToken(
                client_id=client.client_id,
                user_id=u.id,
                access_token=gen_salt(20),
                refresh_token=gen_salt(20),
                expires=_time,
                _scopes="",
                is_personal=False,
                is_internal=True,
            )
            db.session.add(token)

        # Add a client without a last_activity to verify that the cleanup
        # scripts do not break under this condition
        client = OAuthClient(
            user_id=u.id,
            client_id=gen_salt(20),
            client_secret=gen_salt(20),
            is_confidential=False,
            is_internal=True,
            _default_scopes="",
        )
        db.session.add(client)

        # Add a token without an expiry to verify that the cleanup scripts
        # do not break under this condition
        token = OAuthToken(
            client_id=client.client_id,
            user_id=u.id,
            access_token=gen_salt(20),
            refresh_token=gen_salt(20),
            _scopes="",
            is_personal=False,
            is_internal=True,
        )
        db.session.add(token)
        db.session.commit()
コード例 #15
0
def get_token():
    parser = argparse.ArgumentParser()
    add_arguments(parser)
    args = parser.parse_args()
    app = create_app('manual_client_registration',
                     EXTENSIONS=[
                         'adsws.ext.sqlalchemy',
                         'adsws.ext.security',
                     ],
                     PACKAGES=[
                         'adsws.modules.oauth2server',
                     ])

    with app.app_context() as context:
        try:
            u = db.session.query(User).filter_by(email=args.user_email).one()
        except NoResultFound:
            if not args.create_user:
                sys.exit(
                    "User with email [%s] not found, and --create-user was not specified. Exiting."
                    % args.user_email)
            u = User(email=args.user_email)
            db.session.add(u)
            db.session.commit()
        except MultipleResultsFound:
            raise DatabaseIntegrityError

        try:
            client = db.session.query(OAuthClient).filter_by(
                user_id=u.id, name=args.name).one()
        except MultipleResultsFound:
            raise DatabaseIntegrityError(
                "Multiple oauthclients found for that user and name")
        except NoResultFound:
            client = OAuthClient(
                user_id=u.id,
                description=args.description,
                name=args.name,
                is_confidential=True,
                is_internal=True,
            )
            client.gen_salt()
            db.session.add(client)
            db.session.commit()

        try:
            tokens = db.session.query(OAuthToken).filter_by(
                client_id=client.client_id,
                user_id=u.id,
                is_personal=args.is_personal).all()
            #Iterate through each result and compare scopes
            matching_tokens = []
            for t in tokens:
                if set(args.scopes) == set(t.scopes):
                    matching_tokens.append(t)
            if not matching_tokens:
                raise NoResultFound
            print "%s tokens with those definitions found, returning the first" % len(
                matching_tokens)
            token = matching_tokens[0]
        except NoResultFound:
            token = OAuthToken(
                client_id=client.client_id,
                user_id=u.id,
                access_token=gen_salt(
                    current_app.config.get('OAUTH2_TOKEN_PERSONAL_SALT_LEN',
                                           40)),
                refresh_token=gen_salt(
                    current_app.config.get('OAUTH2_TOKEN_PERSONAL_SALT_LEN',
                                           40)),
                _scopes=' '.join(args.scopes),
                expires=datetime.datetime(2050, 1, 1)
                if args.is_personal else None,
                is_personal=args.is_personal,
                is_internal=True,
            )
            db.session.add(token)
            db.session.commit()

        return {
            'access_token': token.access_token,
            'refresh_token': token.refresh_token,
            'username': u.email,
            'expires_in': token.expires.isoformat() if token.expires else None,
            'token_type': 'Bearer'
        }