This is a quick tutorial on how to configure Microsoft (Azure AD) authentication.
First you'll need a registered application in the Microsoft Entra admin center, in order to get your OAuth 2.0 credentials.
- Under the Entra ID fan click App registrations
- Click New registration
- Enter a name for your application
- Under Redirect URI, select Web and enter your callback URL. E.g.
http://localhost:4000/auth/user/microsoft/callback - Click Register
- From the app's Overview page, copy the Application (client) ID — this is your
client_id - From the same Overview page, copy the Directory (tenant) ID — you'll need this if you want to restrict sign-in to a specific tenant
- Navigate to Certificates & secrets > + New client secret, add a description and expiry, then copy the secret Value — this is your
client_secret
Next we configure our resource to use Microsoft credentials:
defmodule MyApp.Accounts.User do
use Ash.Resource,
extensions: [AshAuthentication],
domain: MyApp.Accounts
attributes do
...
end
authentication do
strategies do
microsoft do
client_id MyApp.Secrets
redirect_uri MyApp.Secrets
client_secret MyApp.Secrets
end
end
end
endBy default the strategy uses the common tenant endpoint, which allows any Microsoft
account (personal, work, or school). To restrict sign-in to a specific Azure tenant,
override base_url:
microsoft do
client_id MyApp.Secrets
redirect_uri MyApp.Secrets
client_secret MyApp.Secrets
base_url "https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0"
endPlease check the guide on how to properly configure your Secrets.
Then we need to define an action that will handle the oauth2 flow, for the Microsoft case it is :register_with_microsoft — it will handle both cases for our resource, user registration & login.
defmodule MyApp.Accounts.User do
require Ash.Resource.Change.Builtins
use Ash.Resource,
extensions: [AshAuthentication],
domain: MyApp.Accounts
# ...
actions do
create :register_with_microsoft do
argument :user_info, :map, allow_nil?: false
argument :oauth_tokens, :map, allow_nil?: false
upsert? true
upsert_identity :unique_email
change AshAuthentication.GenerateTokenChange
# Required if you have the `identity_resource` configuration enabled.
change AshAuthentication.Strategy.OAuth2.IdentityChange
change fn changeset, _ ->
user_info = Ash.Changeset.get_argument(changeset, :user_info)
Ash.Changeset.change_attributes(changeset, Map.take(user_info, ["email"]))
end
# Required if you're using the password & confirmation strategies
upsert_fields []
change set_attribute(:confirmed_at, &DateTime.utc_now/0)
end
end
# ...
endEnsure you set the hashed_password to allow_nil? if you are also using the password strategy.
defmodule MyApp.Accounts.User do
# ...
attributes do
# ...
attribute :hashed_password, :string, allow_nil?: true, sensitive?: true
end
# ...
endAnd generate and run migrations in that case.
mix ash.codegen make_hashed_password_nullable
mix ash.migrate