Packages
Easy to install Auth system with social integration just in 6 steps on Elixir Phoenix
Current section
Files
Jump to
Current section
Files
lib/system/strategy.ex
defmodule MishkaAuth.Strategy do
alias MishkaAuth.Client.Users.ClientToken
alias MishkaAuth.Helper.PhoenixConverter
alias MishkaAuth.Client.Users.ClientUserQuery
alias MishkaAuth.Client.Identity.ClientIdentityQuery
@type user_id() :: Ecto.UUID.t
@type redirect_url() :: String.t()
@type strategy_type() :: atom()
@type conn() :: Plug.Conn.t()
@type auth_version() :: float() | integer()
@type error_msg() :: String.t()
@type token() :: String.t()
# Strategies were created
# :current_user // *.html render
# :current_token // *.html render
# :refresh_token // *.json render
# inSite normal current user
@spec registered_user_routing(user_id(), Plug.Conn.t(), :current_user | :current_token | :refresh_token, auth_version()) :: Plug.Conn.t()
def registered_user_routing(user_id, conn, :current_user, 2) do
PhoenixConverter.store_session(:current_user, user_id, MishkaAuth.get_config_info(:user_redirect_path), conn, MishkaAuth.get_config_info(:authenticated_msg))
end
# inSite normal current user with jtw token
def registered_user_routing(user_id, conn, :current_token, 2) do
{:ok, _def_name, token} = ClientToken.create_and_update_current_token(user_id)
PhoenixConverter.store_session(:current_token, token, MishkaAuth.get_config_info(:user_redirect_path), conn, MishkaAuth.get_config_info(:authenticated_msg))
end
# inApi Refresh Token mobile app type, and has backend (external site)
def registered_user_routing(user_id, conn, :refresh_token, 2) do
# create or update refresh token
# save refresh token into redis for some days Like: {10 days}
# create access token
with {:ok, :save_token_into_redis, :create, user_refresh_token, refresh_clime} <- ClientToken.create_and_save_refresh_token(user_id, %{}),
{:ok, :access_token, access_token, access_clime} <- ClientToken.create_and_save_access_token(user_id) do
PhoenixConverter.render_json(conn, %{
refresh_token: user_refresh_token,
refresh_expires_in: refresh_clime["exp"],
refresh_token_type: refresh_clime["typ"],
access_token: access_token,
access_expires_in: access_clime["exp"],
access_token_type: access_clime["typ"]
}, :ok, 200)
else
_ -> PhoenixConverter.render_json(conn, %{error: "Server Error"}, :error, 500)
end
end
# PKCE Refresh Token mobile app type (external site)
@spec none_registered_user_routing(Plug.Conn.t(), map(), user_id(), any(), :refresh_token | :current_user | :current_token) :: Plug.Conn.t()
def none_registered_user_routing(conn, user_temporary_data, temporary_user_uniq_id, status, :refresh_token) do
PhoenixConverter.render_json(conn, %{
user_info: Map.drop(user_temporary_data, ["token", "uid", "provider"]),
temporary_id: temporary_user_uniq_id
}, :ok, status)
end
# it should be improved like auto login after registration.{:current_user, :current_token}
def none_registered_user_routing(conn, user_temporary_data, temporary_user_uniq_id, _status, :current_user) do
saving_user_info_and_indentities(conn, user_temporary_data, temporary_user_uniq_id)
end
def none_registered_user_routing(conn, user_temporary_data, temporary_user_uniq_id, _status, :current_token) do
saving_user_info_and_indentities(conn, user_temporary_data, temporary_user_uniq_id)
end
@spec failed_none_registered_user_routing(Plug.Conn.t(), map(), integer(), :refresh_token | :current_user | :current_token) :: Plug.Conn.t()
def failed_none_registered_user_routing(conn, attrs, status, :refresh_token) do
PhoenixConverter.render_json(conn, attrs, :error, status)
end
def failed_none_registered_user_routing(conn, attrs, _status, :current_user) do
PhoenixConverter.session_redirect(conn, "/", attrs.error, :error)
end
def failed_none_registered_user_routing(conn, attrs, _status, :current_token) do
PhoenixConverter.session_redirect(conn, "/", attrs.error, :error)
end
@spec auth_error_strategy(Plug.Conn.t(), atom(), [any] | map, any) :: Plug.Conn.t()
def auth_error_strategy(conn, strategy_type, errors, status) do
case strategy_type do
:refresh_token ->
PhoenixConverter.render_json(conn, errors, :error, status)
_ ->
error = List.first(errors)
PhoenixConverter.session_redirect(conn, "/", error.message, :error)
end
end
@spec saving_user_info_and_indentities(Plug.Conn.t(), map(), user_id()) :: Plug.Conn.t()
def saving_user_info_and_indentities(conn, user_temporary_data, temporary_user_uniq_id) do
with true <- MishkaAuth.get_config_info(:automatic_registration),
{:ok, :add_user, user_info} <- ClientUserQuery.add_user(user_temporary_data),
{:ok, :add_identity, _identity_info} <- ClientIdentityQuery.add_identity(%{user_id: user_info.id, identity_provider: user_temporary_data["provider"], uid: user_temporary_data["uid"], token: user_temporary_data["token"]}) do
PhoenixConverter.session_redirect(conn, MishkaAuth.get_config_info(:login_redirect), "Your registration was successful.", :info)
else
false ->
PhoenixConverter.register_data(conn, user_temporary_data, temporary_user_uniq_id)
{:error, :add_user, add_user_changeset} ->
PhoenixConverter.changeset_redirect(conn, add_user_changeset)
{:error, :add_identity, _identity_changeset} ->
PhoenixConverter.session_redirect(conn, MishkaAuth.get_config_info(:login_redirect), "An error occurred while saving the social network, Pleas try to login with the social network concerned again.", :error)
end
end
end