Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions spec/System/TestPoEAPIAuth_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
describe("PoEAPI auth", function()
local originalLaunchSubScript
local originalDownloadPage
local originalSubScripts

before_each(function()
originalLaunchSubScript = _G.LaunchSubScript
originalDownloadPage = launch.DownloadPage
originalSubScripts = launch.subScripts
launch.subScripts = { }
end)

after_each(function()
_G.LaunchSubScript = originalLaunchSubScript
launch.DownloadPage = originalDownloadPage
launch.subScripts = originalSubScripts
end)

it("passes token exchange errors to the auth callback #auth", function()
local authState
_G.LaunchSubScript = function(_, _, _, authUrl)
authState = authUrl:match("state=([^&]+)")
return 123
end
launch.DownloadPage = function(_, url, callback)
assert.are.equals("https://www.pathofexile.com/oauth/token", url)
callback(nil, "SSL connect error")
end

local api = new("PoEAPI")
local callbackArgs
api:FetchAuthToken(function(response, errMsg, updateSettings)
callbackArgs = {
response = response,
errMsg = errMsg,
updateSettings = updateSettings,
}
end)

assert.is_not_nil(authState)
assert.is_not_nil(launch.subScripts[123])
launch.subScripts[123].callback("auth-code", nil, authState, 12345)

assert.is_nil(callbackArgs.response)
assert.are.equals("SSL connect error", callbackArgs.errMsg)
assert.True(callbackArgs.updateSettings)
assert.is_nil(api.authToken)
end)

it("reports OAuth state mismatches without exchanging a token", function()
_G.LaunchSubScript = function()
return 123
end
launch.DownloadPage = function()
error("token exchange should not run for mismatched OAuth state")
end

local api = new("PoEAPI")
local callbackArgs
api:FetchAuthToken(function(response, errMsg, updateSettings)
callbackArgs = {
response = response,
errMsg = errMsg,
updateSettings = updateSettings,
}
end)

assert.is_not_nil(launch.subScripts[123])
launch.subScripts[123].callback("auth-code", nil, "wrong-state", 12345)

assert.is_nil(callbackArgs.response)
assert.are.equals("OAuth state mismatch", callbackArgs.errMsg)
assert.True(callbackArgs.updateSettings)
assert.is_nil(api.authToken)
end)
end)
4 changes: 3 additions & 1 deletion src/Classes/ImportTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function(

-- Stage: Authenticate
self.controls.authenticateButton = new("ButtonControl", {"TOPLEFT",self.controls.characterImportAnchor,"TOPLEFT"}, {0, 0, 200, 16}, "^7Authorize with Path of Exile", function()
self.api:FetchAuthToken(function()
self.api:FetchAuthToken(function(_, errMsg)
if self.api.authToken then
self.charImportMode = "GETACCOUNTNAME"
self.charImportStatus = "Authenticated"
Expand All @@ -59,6 +59,8 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function(
main.tokenExpiry = self.api.tokenExpiry
main:SaveSettings()
self:DownloadCharacterList()
elseif errMsg and errMsg ~= self.api.ERROR_NO_AUTH then
self.charImportStatus = colorCodes.NEGATIVE.."Authentication failed: "..errMsg
else
self.charImportStatus = colorCodes.WARNING.."Not authenticated"
end
Expand Down
10 changes: 8 additions & 2 deletions src/Classes/PoEAPI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ local function base64_encode(secret)
return base64.encode(secret):gsub("+","-"):gsub("/","_"):gsub("=$", "")
end

-- func callback(response, errorMsg, updateSettings)
function PoEAPIClass:FetchAuthToken(callback)
math.randomseed(os.time())
local secret = math.random(2^32-1)
Expand Down Expand Up @@ -86,11 +87,16 @@ function PoEAPIClass:FetchAuthToken(callback)
self.authToken = nil
self.refreshToken = nil
self.tokenExpiry = nil
callback(nil, self.ERROR_NO_AUTH, true)
callback(nil, errMsg or self.ERROR_NO_AUTH, true)
return
end

if initialState ~= state then
ConPrintf("OAuth state mismatch during authentication")
self.authToken = nil
self.refreshToken = nil
self.tokenExpiry = nil
callback(nil, "OAuth state mismatch", true)
return
end
local formText = "client_id=pob&grant_type=authorization_code&code=" .. code .. "&redirect_uri=http://localhost:" .. port .. "&scope=" .. table.concat(scopesOAuth, " ") .. "&code_verifier=" .. code_verifier
Expand All @@ -100,7 +106,7 @@ function PoEAPIClass:FetchAuthToken(callback)
self.authToken = nil
self.refreshToken = nil
self.tokenExpiry = nil
callback()
callback(nil, errMsg, true)
return
end
local responseLua = dkjson.decode(response.body)
Expand Down
Loading