Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/hub/auth-token.coffee
Views: 687
#########################################################################1# This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2# License: MS-RSL – see LICENSE.md for details3#########################################################################45###6Temporary authentication token for user.7###89async = require('async')1011random_key = require("random-key")1213misc = require('@cocalc/util/misc')14{defaults, types, required} = misc1516auth = require('./auth')1718# map {account_id:{user_account_id:timestamp}}19ban = {}2021BAN_TIME_MS = 1000*602223exports.get_user_auth_token = (opts) ->24opts = defaults opts, # temporary until types is more than just a WARNING25database : required26account_id : required27user_account_id : required28password : required # admin can get token by using password = ''.29lti : false # LTI auth mode30cb : required31types opts,32database : types.object.isRequired33account_id : types.string.isRequired34user_account_id : types.string.isRequired35password : types.string.isRequired36lti : types.bool # LTI auth mode37cb : types.func.isRequired # cb(err, auth_token)3839auth_token = undefined40b = ban[opts.account_id]?[opts.user_account_id]41if b? and (new Date() - b < BAN_TIME_MS)42opts.cb("banned -- please wait at least #{BAN_TIME_MS/1000}s before trying again")43return4445is_admin = false46is_lti = false4748async.series([49(cb) ->50if opts.password != ''51is_admin = false52cb()53return54if not opts.lti55# must be an admin or NOPE.56opts.database.is_admin57account_id : opts.account_id58cb : (err, _is_admin) =>59is_admin = _is_admin60cb(err)61else62# must have an lti_id63opts.database.get_account64account_id : opts.account_id65columns : ["lti_id"]66cb : (err, lti_id) =>67is_lti = !!lti_id68cb(err)69(cb) ->70if (is_admin or is_lti) and opts.password == ''71# no need to do anything further72cb()73return74# confirm auth75auth.is_password_correct76database : opts.database77account_id : opts.user_account_id78password : opts.password79allow_empty_password : false # user must have a password80cb : (err, is_correct) ->81if err82cb(err)83else if not is_correct84# ban opts.account_id from attempting again for 1 minute (say)85b = ban[opts.account_id] ?= {}86b[opts.user_account_id] = new Date()87cb("incorrect password")88else89cb()90(cb) ->91# generate token92auth_token = random_key.generate(24)93# save in db94opts.database.save_auth_token95account_id : opts.user_account_id96auth_token : auth_token97ttl : 12*3600 # ttl in seconds (12 hours)98cb : cb99(cb) ->100# log that we created an auth_token for an account...101# just in case (this is entirely a security thing)102opts.database.log103event : 'get_user_auth_token'104value : {account_id : opts.account_id, user_account_id:opts.user_account_id, is_admin:is_admin}105cb : cb106107], (err) ->108opts.cb(err, auth_token)109)110111exports.revoke_user_auth_token = (opts) ->112opts = defaults opts,113database : required114auth_token : required115cb : required116types opts,117database : types.object.isRequired118auth_token : types.string.isRequired119cb : types.func.isRequired # cb(err, auth_token)120opts.database.delete_auth_token121auth_token : opts.auth_token122cb : cb123124