connect-vtexid
Version:
VTEX ID Authentication middleware for Connect
170 lines (136 loc) • 5.94 kB
text/coffeescript
###
Module dependencies.
###
NodeCache = require 'node-cache'
request = require 'request'
fs = require 'fs'
colors = require 'colors'
url = require 'url'
WhiteList = require '../libs/white-list'
Logger = require '../libs/logger'
getRedirectSettings = require '../libs/return-url'
parseCookies = require '../libs/cookie-parser'
redirect = require '../libs/redirect'
httpErrorResponse = require '../libs/http-errors'
base64 = require '../libs/base64'
migratedAccounts = ["iam"]
authenticationHandler = (options = {}) ->
FIVE_MINUTES = 5 * 60
options.verbose or= false
options.ttl or= FIVE_MINUTES
options.redirectUrl or= '/admin/login/?ReturnUrl='
options.logoutUrl or= '/admin/logout'
options.replaceWhiteList or= false
options.addToWhiteList or= []
options.useReturnUrl = true if not options.returnUrl?
options.verbose or= false
options.verbosityLevel = 1 if not options.verbosityLevel?
options.migrationEndPoint or= 'https://accounts.vtex.com/index.html#/'
logger = new Logger(options)
logger.logConfigOptions()
logger.logWhiteListProcedure()
whiteList = new WhiteList options.replaceWhiteList
whiteList.addToPublicUris options.redirectUrl
whiteList.addToPublicUris options.addToWhiteList
logger.logWhiteListConfiguration(whiteList)
logger.logCacheSetupProcedure()
cache = new NodeCache stdTTL: options.ttl
(req, res, next) ->
req.vtex or= {}
unauthorized = httpErrorResponse res, 401
# Bypasses authentication if requesting public resource
if whiteList.isInWhiteList(req.url) and req.url.indexOf(options.logoutUrl) is -1
logger.logWhiteListHit(req.url)
return next()
# Gets VTEX ID Return Url
logger.logRedirectUrlSetupProcedure()
redirectSettings = getRedirectSettings options, req.url
logger.logRedirectUrl(redirectSettings.redirectUrl)
# Parses cookies from request
logger.logCookieParsingProcedure()
req.cookies = parseCookies req
# Let user go to logout page
if req.url.indexOf(options.logoutUrl) isnt -1 and req.cookies.VtexIdclientAutCookie?
logger.logUserLogout()
urlParams = url.parse(req.url, true)
if req.headers.originalHost?
referer = req.vtex.store + ".vtexlocal.com.br"
else
referer = req.headers.host
refererRegexp = /([a-zA-Z0-9-$_.+]*)/
match = refererRegexp.exec(referer)
domain = match[1]
expiredDate = new Date()
expiredDate.setYear(2000)
expiredCookieName = "VtexIdclientAutCookie="
expiredDomain = "domain=#{domain}"
expiredDottedDomain = "domain=.#{domain}"
expiredDate = "expires=#{expiredDate.toUTCString()}"
expiredPath = "path=/"
expired = "#{expiredCookieName}; #{expiredDomain}; #{expiredDate}; #{expiredPath}"
expiredDotted = "#{expiredCookieName}; #{expiredDottedDomain}; #{expiredDate}; #{expiredPath}"
expiredWithoutDomain = "#{expiredCookieName}; #{expiredDate}; #{expiredPath}"
res.setHeader('Set-Cookie', expiredWithoutDomain)
res.setHeader('Set-Cookie', expiredDotted)
res.setHeader('Set-Cookie', expired)
urlToRedirect = encodeURIComponent(
urlParams.query.redirectUrl or
"http://" + referer + urlParams.query.previousUrl or
"http://" + referer + redirectSettings.redirectUrl
)
targetUrl = "https://vtexid.vtex.com.br/VtexIdAuthSite/Logout.aspx?urlToRedirect=#{urlToRedirect}"
return redirect(res, targetUrl)
# Gets token from header in CORS
if req.headers and req.headers.vtexidclientautcookie
req.cookies.VtexIdclientAutCookie = req.headers.vtexidclientautcookie
logger.logCookies(req.cookies)
# Redirects to login page if user does not have vtex id cookie
if not req.cookies.VtexIdclientAutCookie
logger.logCookieNotFound()
if (req.vtex.store && (req.vtex.store in migratedAccounts))
if req.query.ott
return next()
fullUrl = 'https://' + req.host + req.originalUrl;
redirectUri = base64.encode fullUrl
redirectUrl = options.migrationEndPoint + req.vtex.store + "/?redirectUri=" + redirectUri
else
redirectUrl = redirectSettings.redirectUrl
return redirect res, redirectUrl
# Checks if vtex id auth info is already cached
logger.logCacheCheck()
cache.get req.cookies.VtexIdclientAutCookie, (err, value) ->
return next(err) if err
if value[req.cookies.VtexIdclientAutCookie]
vtexIdData = value[req.cookies.VtexIdclientAutCookie]
logger.logCachedUser(vtexIdData.user)
req.vtex.vtexIdData = vtexIdData
req.vtex.vtexIdData.fromCache = true
return next()
else
logger.logApiRequest()
vtexIdEndpoint = "https://vtexid.vtex.com.br/api/vtexid/pub/authenticated/user?authToken="
urlEncodedAuthCookie = encodeURIComponent(req.cookies.VtexIdclientAutCookie)
return request.get (vtexIdEndpoint + urlEncodedAuthCookie), (err, response, body) ->
unless body? and body.length > 0
logger.logRedirectToLoginPage()
return redirect(res, options.logoutUrl, req.url)
try
body = JSON.parse(body)
logger.logApiResponseCode(response.statusCode)
unless body?
logger.logRedirectToLoginPage()
return redirect(res, options.logoutUrl, req.url)
if body.error
logger.logRedirectToLoginPage()
return redirect(res, options.logoutUrl, req.url)
unless body.user?
logger.logUnauthorizedUser()
return unauthorized(body)
logger.logCachingUser(body.user)
cache.set req.cookies.VtexIdclientAutCookie, body
req.vtex.vtexIdData = body
req.vtex.vtexIdData.fromCache = false
next()
catch e
return next(e)
module.exports = authenticationHandler