Packages

Azure AD (v2, single tenant) Strategy for Überauth

Current section

2 Versions

Jump to

Compare versions

5 files changed
+161 additions
-29 deletions
  @@ -1,12 +1,28 @@
1 - # Überauth Strategy for Azure AD v2.0, Single Tenant OAuth2
1 + # About
2 +
3 + ## Überauth Azure AD v2.0 Strategy
2 4
3 5 A simple implementation of OAuth that includes the `tenant_id` in the
4 - OAuth2 endpoint, facilitating the Microsoft identity platform version 2.
6 + OAuth2 endpoint, facilitating the Microsoft identity platform version 2. Apart
7 + from the configurable tenant ID, this simply extends the OAuth implementation.
8 +
9 + * author [bvandgrift](http://ben.vandgrift.com)
10 + * github
11 + [bvandgrift/ueberauth_azure_ad](https://github.com/bvandgrift/ueberauth_azure_ad)
5 12
6 13 Originally forked in a hurry from [swelhan/ueberauth_microsoft](http://github.com/swelham/ueberauth_microsoft),
7 14 with much gratitude.
8 15
9 - ## Installation
16 + ## License
17 +
18 + Please see [LICENSE](https://github.com/bvandgrift/ueberauth_azure_ad/blob/master/LICENSE) for licensing details.
19 +
20 + ## Setup
21 +
22 + You can use this strategy by configuring it with your Azure AD tenant and secret
23 + information, then calling the local endpoints as follows:
24 +
25 + ### Configuring
10 26
11 27 1. Setup your application at the new [Microsoft app registration portal](https://apps.dev.microsoft.com).
12 28
  @@ -69,7 +85,7 @@ with much gratitude.
69 85
70 86 For an example implementation see the [Überauth Example](https://github.com/ueberauth/ueberauth_example) application.
71 87
72 - ## Calling
88 + ### Calling
73 89
74 90 Depending on the configured url you can initial the request through:
75 91
  @@ -92,6 +108,3 @@ config :ueberauth, Ueberauth,
92 108 ]
93 109 ```
94 110
95 - ## License
96 -
97 - Please see [LICENSE](https://github.com/bvandgrift/ueberauth_azure_ad/blob/master/LICENSE) for licensing details.
  @@ -2,7 +2,7 @@
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,
4 4 <<"Azure AD (v2, single tenant) Strategy for Überauth"/utf8>>}.
5 - {<<"elixir">>,<<"~> 1.4">>}.
5 + {<<"elixir">>,<<"~> 1.9">>}.
6 6 {<<"files">>,
7 7 [<<"lib">>,<<"lib/ueberauth">>,<<"lib/ueberauth/strategy">>,
8 8 <<"lib/ueberauth/strategy/azure_ad">>,
  @@ -24,4 +24,4 @@
24 24 {<<"optional">>,false},
25 25 {<<"repository">>,<<"hexpm">>},
26 26 {<<"requirement">>,<<"~> 0.6">>}]]}.
27 - {<<"version">>,<<"0.5.1">>}.
27 + {<<"version">>,<<"0.5.2">>}.
  @@ -1,4 +1,93 @@
1 1 defmodule Ueberauth.Strategy.AzureAD do
2 + @moduledoc """
3 + provides an Ueberauth strategy for authenticating against OAuth2
4 + endpoints in Microsoft Identity (Azure) 2.0.
5 +
6 + ## Setup
7 +
8 + 1. Setup your application at the new [Microsoft app registration portal](https://apps.dev.microsoft.com).
9 + 1. Add `:ueberauth_azure_ad` to your list of dependencies in `mix.exs`:
10 +
11 + ```elixir
12 + def deps do
13 + [{:ueberauth_azure_ad, "~> 0.5"}]
14 + end
15 + ```
16 +
17 + 1. Add the strategy to your applications:
18 +
19 + ```elixir
20 + def application do
21 + [applications: [:ueberauth_azure_ad]]
22 + end
23 + ```
24 +
25 + 1. Add Microsoft to your Überauth configuration:
26 +
27 + ```elixir
28 + config :ueberauth, Ueberauth,
29 + providers: [
30 + azure: {Ueberauth.Strategy.AzureAD, []}
31 + ]
32 + ```
33 +
34 + 1. Update your provider configuration:
35 +
36 + ```elixir
37 + config :ueberauth, Ueberauth.Strategy.AzureAD.OAuth,
38 + client_id: System.get_env("AZURE_CLIENT_ID"),
39 + client_secret: System.get_env("AZURE_CLIENT_SECRET"),
40 + tenant_id: System.get_env("AZURE_TENANT_ID")
41 + ```
42 +
43 + 1. Include the Überauth plug in your controller:
44 +
45 + ```elixir
46 + defmodule MyApp.AuthController do
47 + use MyApp.Web, :controller
48 + plug Ueberauth
49 + ...
50 + end
51 + ```
52 +
53 + 1. Create the request and callback routes if you haven't already:
54 +
55 + ```elixir
56 + scope "/auth", MyApp do
57 + pipe_through :browser
58 +
59 + get "/:provider", AuthController, :request
60 + get "/:provider/callback", AuthController, :callback
61 + end
62 + ```
63 +
64 + 1. Your controller needs to implement callbacks to deal with `Ueberauth.Auth` and `Ueberauth.Failure` responses.
65 +
66 + For an example implementation see the [Überauth Example](https://github.com/ueberauth/ueberauth_example) application.
67 +
68 + ## Calling
69 +
70 + Depending on the configured url you can initial the request through:
71 +
72 + /auth/azure
73 +
74 + By default the scopes used are
75 + * openid
76 + * email
77 + * offline_access
78 + * https://graph.microsoft.com/user.read
79 +
80 + *Note: at least one service scope is required in order for a token to be returned by the Microsoft endpoint*
81 +
82 + You can configure additional scopes to be used by passing the `extra_scopes` option into the provider
83 +
84 + ```elixir
85 + config :ueberauth, Ueberauth,
86 + providers: [
87 + azure: {Ueberauth.Strategy.AzureAD, [extra_scopes: "https://graph.microsoft.com/calendars.read"]}
88 + ]
89 + ```
90 + """
2 91 use Ueberauth.Strategy,
3 92 default_scope: "https://graph.microsoft.com/user.read openid email offline_access",
4 93 uid_field: :id
  @@ -56,6 +145,7 @@ defmodule Ueberauth.Strategy.AzureAD do
56 145 |> put_private(:ms_user, nil)
57 146 end
58 147
148 + @doc false
59 149 def uid(conn) do
60 150 user =
61 151 conn
  @@ -65,6 +155,7 @@ defmodule Ueberauth.Strategy.AzureAD do
65 155 conn.private.ms_user[user]
66 156 end
67 157
158 + @doc false
68 159 def credentials(conn) do
69 160 token = conn.private.ms_token
70 161
  @@ -78,6 +169,7 @@ defmodule Ueberauth.Strategy.AzureAD do
78 169 }
79 170 end
80 171
172 + @doc false
81 173 def info(conn) do
82 174 user = conn.private.ms_user
83 175
  @@ -89,6 +181,7 @@ defmodule Ueberauth.Strategy.AzureAD do
89 181 }
90 182 end
91 183
184 + @doc false
92 185 def extra(conn) do
93 186 %Extra{
94 187 raw_info: %{
  @@ -1,4 +1,7 @@
1 1 defmodule Ueberauth.Strategy.AzureAD.OAuth do
2 + @moduledoc """
3 + configures OAuth2 client for use with Microsoft Identity (Azure AD) 2.0.
4 + """
2 5 use OAuth2.Strategy
3 6
4 7 alias OAuth2.Client
  @@ -10,6 +13,9 @@ defmodule Ueberauth.Strategy.AzureAD.OAuth do
10 13 request_opts: [ssl_options: [versions: [:"tlsv1.2"]]]
11 14 ]
12 15
16 + @doc """
17 + configures the authorization and token URLs from the tenant id
18 + """
13 19 def client(opts \\ []) do
14 20 config = Application.get_env(:ueberauth, Ueberauth.Strategy.AzureAD.OAuth)
15 21
  @@ -25,28 +31,41 @@ defmodule Ueberauth.Strategy.AzureAD.OAuth do
25 31 |> Client.new()
26 32 end
27 33
28 - def authorize_url!(params \\ [], opts \\ []) do
29 - opts
30 - |> client
31 - |> Client.authorize_url!(params)
32 - end
33 -
34 + @doc """
35 + extract token from client, possibly throwing exception
36 + """
34 37 def get_token!(params \\ [], opts \\ []) do
35 38 opts
36 39 |> client
37 40 |> Client.get_token!(params)
38 41 end
39 42
40 - # oauth2 Strategy Callbacks
41 -
42 - def authorize_url(client, params) do
43 - AuthCode.authorize_url(client, params)
44 - end
45 -
43 + @doc """
44 + extract token from client
45 + """
46 46 def get_token(client, params, headers) do
47 47 client
48 48 |> put_param(:client_secret, client.client_secret)
49 49 |> put_header("Accept", "application/json")
50 50 |> AuthCode.get_token(params, headers)
51 51 end
52 +
53 + # oauth2 Strategy Callbacks
54 +
55 + @doc """
56 + returns authorize url from client, given params
57 + """
58 + def authorize_url(client, params) do
59 + AuthCode.authorize_url(client, params)
60 + end
61 +
62 + @doc """
63 + returns authorize url from client, given params, may throw exception
64 + """
65 + def authorize_url!(params \\ [], opts \\ []) do
66 + opts
67 + |> client
68 + |> Client.authorize_url!(params)
69 + end
70 +
52 71 end
  @@ -2,14 +2,21 @@ defmodule UeberauthAzureAD.Mixfile do
2 2 use Mix.Project
3 3
4 4 def project do
5 - [app: :ueberauth_azure_ad,
6 - version: "0.5.1",
7 - elixir: "~> 1.4",
8 - description: description(),
9 - package: package(),
10 - build_embedded: Mix.env == :prod,
11 - start_permanent: Mix.env == :prod,
12 - deps: deps()]
5 + [
6 + app: :ueberauth_azure_ad,
7 + version: "0.5.2",
8 + elixir: "~> 1.9",
9 + description: description(),
10 + package: package(),
11 + build_embedded: Mix.env == :prod,
12 + start_permanent: Mix.env == :prod,
13 + deps: deps(),
14 + docs: [
15 + main: "readme",
16 + extras: ["README.md"]
17 + ]
18 +
19 + ]
13 20 end
14 21
15 22 # Configuration for the OTP application