blob: e06b3e69c36c71d43914135751a39ebcdde8f838 [file] [log] [blame]
--[[
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
-- This is oauth.lua - an oauth providing script for ponymail
local JSON = require 'cjson'
local http = require 'socket.http'
local elastic = require 'lib/elastic'
local https = require 'ssl.https'
local user = require 'lib/user'
local cross = require 'lib/cross'
function handle(r)
r.content_type = "application/json"
local get = r:parseargs()
local post = r:parsebody()
local valid, json
local scheme = "https"
if r.port == 80 then
scheme = "http"
end
-- Persona callback
if get.mode and get.mode == "persona" then
local result = https.request("https://verifier.login.persona.org/verify", ("assertion=%s&audience=%s://%s:%u/"):format(post.assertion, scheme, r.hostname, r.port))
r:err(("assertion=%s&audience=%s://ponymail:443/"):format(post.assertion, scheme))
r:err(result)
valid, json = pcall(function() return JSON.decode(result) end)
-- Google Auth callback
elseif get.oauth_token and get.oauth_token:match("^https://www.google") and get.id_token then
local result = https.request("https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" .. r:escape(get.id_token))
r:err(result)
r:err(r:escape(get.id_token))
valid, json = pcall(function() return JSON.decode(result) end)
-- Generic callback (like ASF Oauth2)
elseif get.state and get.code and get.oauth_token then
local result = https.request(get.oauth_token, r.args)
valid, json = pcall(function() return JSON.decode(result) end)
end
-- Did we get something useful from the backend?
if valid and json then
local eml = json.email
local fname = json.fullname or json.name or json.email
local admin = json.isMember
-- If we got an email and a name, log in the user and set cookie etc
if eml and fname then
local cid = json.uid or json.email
-- Does the user exist already?
local oaccount = user.get(r, cid)
local usr = {}
if oaccount then
usr.preferences = oaccount.preferences
else
usr.preferences = {}
end
usr.gauth = get.id_token
usr.fullname = fname
usr.admin = admin
usr.email = eml
usr.uid = json.uid
user.update(r, cid, usr)
r:puts[[{"okay": true, "msg": "Logged in successfully!"}]]
-- didn't get email or name, bork!
else
r:puts[[{"okay": false, "msg": "Erroneous or missing response from backend!"}]]
end
-- Backend borked, let the user know
else
r:puts[[{"okay": false, "msg": "Invalid oauth response!"}]]
end
return cross.OK
end
cross.start(handle)