Skip to content

Commit 547d3ce

Browse files
authored
security: verify GitHub OAuth state (#24)
1 parent 829b762 commit 547d3ce

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

lib/algora/integrations/github/github.ex

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,18 @@ defmodule Algora.Github do
1717
"https://github.com/apps/#{app_handle()}/installations/new"
1818
end
1919

20-
def authorize_url(_return_to \\ nil) do
20+
defp oauth_state_ttl, do: 600
21+
defp oauth_state_salt, do: "github-oauth-state"
22+
23+
def generate_oauth_state(data) do
24+
Phoenix.Token.sign(AlgoraWeb.Endpoint, oauth_state_salt(), data, max_age: oauth_state_ttl())
25+
end
26+
27+
def verify_oauth_state(token) do
28+
Phoenix.Token.verify(AlgoraWeb.Endpoint, oauth_state_salt(), token, max_age: oauth_state_ttl())
29+
end
30+
31+
def authorize_url(data \\ nil) do
2132
# TODO: find out a way to set return_to w/o github complaining about redirect_uri mismatch
2233

2334
# redirect_query = if return_to, do: URI.encode_query(return_to: return_to)
@@ -28,7 +39,7 @@ defmodule Algora.Github do
2839
query =
2940
URI.encode_query(
3041
client_id: client_id(),
31-
state: Algora.Util.random_string(),
42+
state: generate_oauth_state(data),
3243
redirect_uri: redirect_uri
3344
)
3445

lib/algora_web/controllers/oauth_callback_controller.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ defmodule AlgoraWeb.OAuthCallbackController do
1515
end
1616

1717
def new(conn, %{"provider" => "github", "code" => code, "state" => state} = params) do
18-
with {:ok, info} <- Github.OAuth.exchange_access_token(code: code, state: state),
18+
with {:ok, _data} <- Github.verify_oauth_state(state),
19+
{:ok, info} <- Github.OAuth.exchange_access_token(code: code, state: state),
1920
%{info: info, primary_email: primary, emails: emails, token: token} = info,
2021
{:ok, user} <- Accounts.register_github_user(primary, info, emails, token) do
2122
conn =
@@ -29,14 +30,21 @@ defmodule AlgoraWeb.OAuthCallbackController do
2930
|> put_flash(:info, welcome_message(user))
3031
|> AlgoraWeb.UserAuth.log_in_user(user)
3132
else
33+
{:error, :invalid} ->
34+
conn
35+
|> put_flash(:error, "Unable to verify your login request. Please try signing in again.")
36+
|> redirect(to: "/")
37+
38+
{:error, :expired} ->
39+
conn
40+
|> put_flash(:error, "Your login link has expired. Please request a new one to continue.")
41+
|> redirect(to: "/")
42+
3243
{:error, %Ecto.Changeset{} = changeset} ->
3344
Logger.debug("failed GitHub insert #{inspect(changeset.errors)}")
3445

3546
conn
36-
|> put_flash(
37-
:error,
38-
"We were unable to fetch the necessary information from your GitHub account"
39-
)
47+
|> put_flash(:error, "We were unable to fetch the necessary information from your GitHub account")
4048
|> redirect(to: "/")
4149

4250
{:error, reason} ->

0 commit comments

Comments
 (0)