Remove support for legacy auth

This commit is contained in:
Adrian Kumpf
2021-01-30 18:02:24 +01:00
parent e3e91134e4
commit 3bb2d3086f
7 changed files with 11 additions and 163 deletions
-18
View File
@@ -10,19 +10,6 @@ defmodule TeslaApi.Auth do
defdelegate login(email, password), to: MFA
defdelegate login(device_id, mfa_passcode, ctx), to: MFA
def legacy_login(email, password) do
data = %{
grant_type: "password",
client_id: @client_id,
client_secret: @client_secret,
email: email,
password: password
}
TeslaApi.post("/oauth/token", data)
|> handle_response()
end
def refresh(%__MODULE__{token: token, refresh_token: refresh_token}) do
data = %{
grant_type: "refresh_token",
@@ -35,11 +22,6 @@ defmodule TeslaApi.Auth do
|> handle_response()
end
def revoke(%__MODULE__{token: token}) do
TeslaApi.post("/oauth/revoke", %{token: token}, opts: [access_token: token])
|> handle_response()
end
defp handle_response(response) do
case response do
{:ok, %Tesla.Env{status: 200, body: body}} when body == %{} ->
-1
View File
@@ -115,7 +115,6 @@ defmodule TeslaMate.Api do
@impl true
def handle_call({:sign_in, args}, _, state) do
case args do
[%Credentials{use_legacy_auth: true} = c] -> Auth.legacy_login(c.email, c.password)
[%Credentials{} = c] -> Auth.login(c.email, c.password)
[device_id, passcode, ctx] -> Auth.login(device_id, passcode, ctx)
end
+1 -2
View File
@@ -5,13 +5,12 @@ defmodule TeslaMate.Auth.Credentials do
schema "" do
field :email, :string
field :password, :string
field :use_legacy_auth, :boolean, default: false
end
@doc false
def changeset(credentials, attrs) do
credentials
|> cast(attrs, [:email, :password, :use_legacy_auth])
|> cast(attrs, [:email, :password])
|> validate_required([:email, :password])
end
end
+8 -24
View File
@@ -13,26 +13,24 @@ defmodule TeslaMateWeb.SignInLive.Index do
page_title: gettext("Sign in"),
error: nil,
task: nil,
state: {:credentials, {Auth.change_credentials(), _show_checkbox = false}}
state: {:credentials, Auth.change_credentials()}
}
{:ok, assign(socket, assigns)}
end
@impl true
def handle_event("validate", %{"credentials" => c}, %{assigns: %{state: {:credentials, d}}} = s) do
{_changeset, show_checkbox?} = d
def handle_event("validate", %{"credentials" => c}, %{assigns: %{state: {:credentials, _}}} = s) do
changeset =
c
|> Auth.change_credentials()
|> Map.put(:action, :update)
{:noreply, assign(s, state: {:credentials, {changeset, show_checkbox?}}, error: nil)}
{:noreply, assign(s, state: {:credentials, changeset}, error: nil)}
end
def handle_event("validate", %{"mfa" => mfa}, %{assigns: %{state: {:mfa, data}}} = socket) do
{_changeset, devices, ctx, show_button?} = data
{_changeset, devices, ctx} = data
changeset =
mfa
@@ -48,12 +46,12 @@ defmodule TeslaMateWeb.SignInLive.Index do
end)
end
state = {:mfa, {changeset, devices, ctx, show_button?}}
state = {:mfa, {changeset, devices, ctx}}
{:noreply, assign(socket, state: state, task: task, error: nil)}
end
def handle_event("sign_in", _, %{assigns: %{state: {:credentials, {changeset, _}}}} = socket) do
def handle_event("sign_in", _, %{assigns: %{state: {:credentials, changeset}}} = socket) do
credentials = Ecto.Changeset.apply_changes(changeset)
task =
@@ -64,11 +62,6 @@ defmodule TeslaMateWeb.SignInLive.Index do
{:noreply, assign(socket, task: task)}
end
def handle_event("use_legacy_login", _params, %{assigns: %{state: {:mfa, _data}}} = socket) do
state = {:credentials, {Auth.change_credentials(%{use_legacy_auth: true}), true}}
{:noreply, assign(socket, state: state)}
end
@impl true
def handle_info({ref, result}, %{assigns: %{task: %Task{ref: ref}}} = socket) do
Process.demonitor(ref, [:flush])
@@ -80,20 +73,11 @@ defmodule TeslaMateWeb.SignInLive.Index do
{:ok, {:mfa, devices, ctx}} ->
devices = Enum.map(devices, fn %{"name" => name, "id" => id} -> {name, id} end)
state = {:mfa, {mfa_changeset(), devices, ctx, false}}
state = {:mfa, {mfa_changeset(), devices, ctx}}
{:noreply, assign(socket, state: state, task: nil)}
{:error, %TeslaApi.Error{} = e} ->
state =
case socket.assigns.state do
{:credentials, {changeset, _show_checkbox}} ->
{:credentials, {changeset, true}}
{:mfa, {changeset, devices, ctx, _show_button}} ->
{:mfa, {changeset, devices, ctx, true}}
end
{:noreply, assign(socket, state: state, error: Exception.message(e), task: nil)}
{:noreply, assign(socket, error: Exception.message(e), task: nil)}
end
end
@@ -1,7 +1,7 @@
<div class="mfa columns is-tablet is-centered">
<div class="column is-half">
<%= case @state do %>
<% {:credentials, {changeset, show_checkbox?}} -> %>
<% {:credentials, changeset} -> %>
<%= f = form_for changeset, "#", [phx_change: :validate, phx_submit: :sign_in, class: "box"] %>
<%= if @error do %>
<div class="notification is-danger">
@@ -34,17 +34,6 @@
</div>
</div>
<%= if show_checkbox? do %>
<div class="field">
<div class="control">
<label class="checkbox">
<%= checkbox f, :use_legacy_auth, disabled: !!@task %>
<%= gettext "Use legacy authentication API" %>
</label>
</div>
</div>
<% end %>
<div class="field mt-20">
<div class="control">
<%= submit gettext("Sign in"), class: "button is-rounded is-fullwidth is-link#{if !!@task, do: " is-loading" }",
@@ -55,7 +44,7 @@
</div>
</form>
<% {:mfa, {changeset, devices, _ctx, show_button?}} -> %>
<% {:mfa, {changeset, devices, _ctx}} -> %>
<%= f = form_for changeset, "#", [phx_change: :validate, class: "box", as: :mfa] %>
<h3 class="title is-4 is-spaced has-text-centered">
<%= gettext "Two-Factor Authentication" %>
@@ -92,21 +81,6 @@
</div>
</div>
</div>
<%= if show_button? do %>
<hr style="margin-top: 0;"/>
<div class="field">
<div class="control">
<button type="button" class="button is-warning is-light is-small is-rounded is-fullwidth"
phx-click="use_legacy_login" <%= if !!@task, do: "disabled" %>>
<span class="icon"><i class="mdi mdi-login"></i></span>&nbsp;<span><%=
gettext "Use legacy authentication API"
%></span>
</button>
</div>
</div>
<% end %>
</form>
<% end %>
</div>
-21
View File
@@ -55,10 +55,6 @@ defmodule TeslaMate.ApiTest do
send(pid, {TeslaApi.Auth, {:login, email, password}})
{:ok, %TeslaApi.Auth{token: "$token", refresh_token: "$token", expires_in: 10_000_000}}
end,
legacy_login: fn email, password ->
send(pid, {TeslaApi.Auth, {:legacy_login, email, password}})
{:ok, %TeslaApi.Auth{token: "$token", refresh_token: "$token", expires_in: 10_000_000}}
end,
refresh: fn
%{token: "cannot_be_refreshed", refresh_token: "cannot_be_refreshed"} = auth ->
send(pid, {TeslaApi.Auth, {:refresh, auth}})
@@ -144,23 +140,6 @@ defmodule TeslaMate.ApiTest do
end
end
test "uses legacy login", %{test: name} do
with_mocks [auth_mock(self()), vehicle_mock(self())] do
:ok = start_api(name, tokens: nil)
assert false == Api.signed_in?(name)
assert :ok = Api.sign_in(name, %Credentials{@valid_credentials | use_legacy_auth: true})
assert_receive {TeslaApi.Auth, {:legacy_login, "teslamate", "foo"}}
assert_receive {AuthMock, {:save, %TeslaApi.Auth{}}}
assert_receive {VehiclesMock, :restart}
assert true == Api.signed_in?(name)
refute_receive _
end
end
test "fails if already signed in", %{test: name} do
with_mocks [auth_mock(self()), vehicle_mock(self())] do
:ok = start_api(name, tokens: @valid_tokens)
-69
View File
@@ -89,73 +89,4 @@ defmodule TeslaMateWeb.SignInLiveTest do
assert_receive {ApiMock, {:sign_in, "111", "123456", %TeslaApi.Auth.MFA.Ctx{}}}
assert_redirect(view, "/", 1000)
end
test "offers to sign in via the legacy API", %{conn: conn, test: name} do
params = start_api(name)
assert {:ok, view, html} =
conn
|> put_connect_params(params)
|> live("/sign_in")
assert [] ==
html
|> Floki.parse_document!()
|> Floki.find("#credentials_use_legacy_auth")
render_change(view, :validate, %{credentials: %{email: "error", password: ""}})
render_submit(view, :sign_in, %{})
assert [{"input", [_, _, {"type", "checkbox"}, {"value", "true"}], []}] =
view
|> render()
|> Floki.parse_document!()
|> Floki.find("#credentials_use_legacy_auth")
render_change(view, :validate, %{
credentials: %{email: "$email", password: "$password", use_legacy_auth: true}
})
render_submit(view, :sign_in, %{})
assert_receive {ApiMock,
{:sign_in,
%Credentials{email: "$email", password: "$password", use_legacy_auth: true}}}
assert_redirect(view, "/", 1000)
end
test "offers to sign in via the legacy API if 2FA step failed", %{conn: conn, test: name} do
params = start_api(name)
assert {:ok, view, _html} =
conn
|> put_connect_params(params)
|> live("/sign_in")
render_change(view, :validate, %{credentials: %{email: "mfa", password: "$password"}})
render_submit(view, :sign_in, %{})
assert_receive {ApiMock, {:sign_in, %Credentials{email: "mfa", password: "$password"}}}
assert [{"div", _, [{"select", [{"id", "mfa_device_id"} | _], _options}]}] =
view
|> render_change(:validate, %{mfa: %{device_id: "error", passcode: "999999"}})
|> Floki.parse_document!()
|> Floki.find(".is-loading")
assert_receive {ApiMock, {:sign_in, "error", "999999", %TeslaApi.Auth.MFA.Ctx{}}}
assert [{"button", _, [_icon, " ", {"span", _, ["Use legacy authentication API"]}]}] =
view
|> render()
|> Floki.parse_document!()
|> Floki.find("button[phx-click='use_legacy_login']")
assert [{"input", [_, _, {"type", "checkbox"}, {"value", "true"}, {"checked", "checked"}], _}] =
view
|> render_click(:use_legacy_login)
|> Floki.parse_document!()
|> Floki.find("#credentials_use_legacy_auth")
end
end