Packages
phoenix_kit
1.7.145
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit/users/oauth_config.ex
defmodule PhoenixKit.Users.OAuthConfig do
@moduledoc """
Runtime OAuth configuration management using database credentials.
This module provides functions to configure OAuth providers at runtime
by reading credentials from the database and updating the application
configuration dynamically.
"""
alias PhoenixKit.Config
alias PhoenixKit.Settings
require Logger
@doc """
Configures all OAuth providers from database settings.
This function reads OAuth credentials from the database and updates
the application configuration at runtime. It should be called:
- On application startup
- After updating OAuth credentials via admin UI
Skips configuration if OAuth is disabled in settings (oauth_enabled = false).
## Examples
iex> PhoenixKit.Users.OAuthConfig.configure_providers()
:ok
"""
def configure_providers do
# Always configure Ueberauth base with available providers
# This ensures Ueberauth has providers configured even if oauth_enabled is false
# The oauth_enabled flag controls UI visibility, not the underlying OAuth infrastructure
configure_ueberauth_base()
configure_google()
configure_apple()
configure_github()
configure_facebook()
:ok
end
@doc """
Configures a specific OAuth provider from database settings.
## Examples
iex> PhoenixKit.Users.OAuthConfig.configure_provider(:google)
:ok
"""
def configure_provider(provider) when provider in [:google, :apple, :github, :facebook] do
case provider do
:google -> configure_google()
:apple -> configure_apple()
:github -> configure_github()
:facebook -> configure_facebook()
end
end
# Configure base Ueberauth with available providers
defp configure_ueberauth_base do
providers = build_provider_list()
base_path = PhoenixKit.Config.UeberAuth.get_base_path()
# Use PhoenixKit.Config.UeberAuth to set the configuration
Config.UeberAuth.set_all(
base_path: base_path,
providers: providers
)
if providers != %{} do
Logger.info(
"OAuth: Configured Ueberauth with providers: #{inspect(Map.keys(providers))} at base_path: #{base_path}"
)
else
Logger.info(
"OAuth: Configured Ueberauth with no active providers at base_path: #{base_path}"
)
end
end
# Build the list of available providers based on configured credentials
# Uses direct database reads to avoid cache race conditions
defp build_provider_list do
providers = %{}
# Add Google if credentials exist (direct DB read)
providers =
if Settings.has_oauth_credentials_direct?(:google) and
Settings.get_boolean_setting("oauth_google_enabled", false) do
Map.put(providers, :google, {Ueberauth.Strategy.Google, []})
else
providers
end
# Add Apple if credentials exist (direct DB read)
providers =
if Settings.has_oauth_credentials_direct?(:apple) and
Settings.get_boolean_setting("oauth_apple_enabled", false) do
Map.put(providers, :apple, {Ueberauth.Strategy.Apple, []})
else
providers
end
# Add GitHub if credentials exist (direct DB read)
providers =
if Settings.has_oauth_credentials_direct?(:github) and
Settings.get_boolean_setting("oauth_github_enabled", false) do
Map.put(providers, :github, {Ueberauth.Strategy.Github, []})
else
providers
end
# Add Facebook if credentials exist (direct DB read)
providers =
if Settings.has_oauth_credentials_direct?(:facebook) and
Settings.get_boolean_setting("oauth_facebook_enabled", false) do
Map.put(providers, :facebook, {Ueberauth.Strategy.Facebook, []})
else
providers
end
providers
end
# Configure Google OAuth
# Uses direct DB read to avoid cache race conditions after settings update
defp configure_google do
if Settings.get_boolean_setting("oauth_google_enabled", false) do
credentials = Settings.get_oauth_credentials_direct(:google)
if credentials.client_id != "" and credentials.client_secret != "" do
config = [
client_id: credentials.client_id,
client_secret: credentials.client_secret
]
Config.UeberAuth.set_provider_strategy_config(
:google,
Ueberauth.Strategy.Google.OAuth,
config
)
Logger.info("OAuth: Configured Google OAuth provider")
else
Logger.warning("OAuth: Google enabled but credentials not configured")
end
end
end
# Configure Apple OAuth
# Uses direct DB read to avoid cache race conditions after settings update
defp configure_apple do
if Settings.get_boolean_setting("oauth_apple_enabled", false) do
credentials = Settings.get_oauth_credentials_direct(:apple)
if credentials.client_id != "" and
credentials.team_id != "" and
credentials.key_id != "" and
credentials.private_key != "" do
config = [
client_id: credentials.client_id,
team_id: credentials.team_id,
key_id: credentials.key_id,
private_key: credentials.private_key
]
Config.UeberAuth.set_provider_strategy_config(
:apple,
Ueberauth.Strategy.Apple.OAuth,
config
)
Logger.info("OAuth: Configured Apple OAuth provider")
else
Logger.warning("OAuth: Apple enabled but credentials not fully configured")
end
end
end
# Configure GitHub OAuth
# Uses direct DB read to avoid cache race conditions after settings update
defp configure_github do
if Settings.get_boolean_setting("oauth_github_enabled", false) do
credentials = Settings.get_oauth_credentials_direct(:github)
if credentials.client_id != "" and credentials.client_secret != "" do
config = [
client_id: credentials.client_id,
client_secret: credentials.client_secret
]
Config.UeberAuth.set_provider_strategy_config(
:github,
Ueberauth.Strategy.Github.OAuth,
config
)
Logger.info("OAuth: Configured GitHub OAuth provider")
else
Logger.warning("OAuth: GitHub enabled but credentials not configured")
end
end
end
# Configure Facebook OAuth
# Uses direct DB read to avoid cache race conditions after settings update
defp configure_facebook do
if Settings.get_boolean_setting("oauth_facebook_enabled", false) do
credentials = Settings.get_oauth_credentials_direct(:facebook)
if credentials.app_id != "" and credentials.app_secret != "" do
config = [
client_id: credentials.app_id,
client_secret: credentials.app_secret
]
Config.UeberAuth.set_provider_strategy_config(
:facebook,
Ueberauth.Strategy.Facebook.OAuth,
config
)
Logger.info("OAuth: Configured Facebook OAuth provider")
else
Logger.warning("OAuth: Facebook enabled but credentials not configured")
end
end
end
@doc """
Validates OAuth credentials for a specific provider.
Returns `{:ok, provider}` if credentials are valid, or `{:error, reason}` if not.
Uses direct database read for accurate validation.
## Examples
iex> PhoenixKit.Users.OAuthConfig.validate_credentials(:google)
{:ok, :google}
iex> PhoenixKit.Users.OAuthConfig.validate_credentials(:apple)
{:error, "Missing Apple private key"}
"""
def validate_credentials(provider) when provider in [:google, :apple, :github, :facebook] do
credentials = Settings.get_oauth_credentials_direct(provider)
case provider do
:google -> validate_google_credentials(credentials)
:apple -> validate_apple_credentials(credentials)
:github -> validate_github_credentials(credentials)
:facebook -> validate_facebook_credentials(credentials)
end
end
defp validate_google_credentials(credentials) do
missing = find_missing_google_credentials(credentials)
if missing == [] do
{:ok, :google}
else
{:error, "Missing Google OAuth credentials: #{Enum.join(missing, ", ")}"}
end
end
defp validate_apple_credentials(credentials) do
missing = find_missing_apple_credentials(credentials)
if missing == [] do
{:ok, :apple}
else
{:error, "Missing Apple OAuth credentials: #{Enum.join(missing, ", ")}"}
end
end
defp validate_github_credentials(credentials) do
missing = find_missing_github_credentials(credentials)
if missing == [] do
{:ok, :github}
else
{:error, "Missing GitHub OAuth credentials: #{Enum.join(missing, ", ")}"}
end
end
defp find_missing_google_credentials(credentials) do
[]
|> add_if_missing("Client ID", credentials.client_id)
|> add_if_missing("Client Secret", credentials.client_secret)
end
defp find_missing_apple_credentials(credentials) do
[]
|> add_if_missing("Client ID", credentials.client_id)
|> add_if_missing("Team ID", credentials.team_id)
|> add_if_missing("Key ID", credentials.key_id)
|> add_if_missing("Private Key", credentials.private_key)
end
defp find_missing_github_credentials(credentials) do
[]
|> add_if_missing("Client ID", credentials.client_id)
|> add_if_missing("Client Secret", credentials.client_secret)
end
defp validate_facebook_credentials(credentials) do
missing = find_missing_facebook_credentials(credentials)
if missing == [] do
{:ok, :facebook}
else
{:error, "Missing Facebook OAuth credentials: #{Enum.join(missing, ", ")}"}
end
end
defp find_missing_facebook_credentials(credentials) do
[]
|> add_if_missing("App ID", credentials.app_id)
|> add_if_missing("App Secret", credentials.app_secret)
end
defp add_if_missing(list, field_name, value) do
if value == "" do
[field_name | list]
else
list
end
end
@doc """
Tests OAuth connection for a specific provider.
This function validates the credentials format but does not make actual API calls.
For true connection testing, OAuth flow needs to be initiated through the browser.
## Examples
iex> PhoenixKit.Users.OAuthConfig.test_connection(:google)
{:ok, "Google OAuth credentials are properly formatted"}
"""
def test_connection(provider) when provider in [:google, :apple, :github, :facebook] do
case validate_credentials(provider) do
{:ok, _provider} ->
Logger.info(
"OAuth: #{provider_name(provider)} connection test successful - credentials validated"
)
{:ok,
"#{provider_name(provider)} OAuth credentials are properly formatted. Initiate OAuth flow to test actual connection."}
{:error, reason} ->
Logger.warning("OAuth: #{provider_name(provider)} connection test failed: #{reason}")
{:error, reason}
end
end
defp provider_name(:google), do: "Google"
defp provider_name(:apple), do: "Apple"
defp provider_name(:github), do: "GitHub"
defp provider_name(:facebook), do: "Facebook"
end