From a75dfa3073f8d0aeeaf962f33cef130466024fda Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 30 Jun 2022 12:30:42 -0500 Subject: [PATCH] Add redirect routes for oidc signin links by provider (#770) * Add redirect routes for oidc signin links by provider * whitespace fix * restore comment * Add oidc redirect route helper to auth template for sign-in buttons * Update docs to mention pretty URLs. * Fix docs --- .../fz_http_web/controllers/auth_controller.ex | 16 ++++++++++++++++ .../fz_http_web/controllers/root_controller.ex | 3 +-- apps/fz_http/lib/fz_http_web/router.ex | 1 + .../fz_http_web/templates/root/auth.html.heex | 5 +++-- apps/fz_http/lib/fz_http_web/views/root_view.ex | 12 ------------ .../controllers/auth_controller_test.exs | 16 ++++++++++++++++ docs/docs/authenticate/index.md | 11 +++++++++++ 7 files changed, 48 insertions(+), 16 deletions(-) diff --git a/apps/fz_http/lib/fz_http_web/controllers/auth_controller.ex b/apps/fz_http/lib/fz_http_web/controllers/auth_controller.ex index 3bda6ce53..5978c475a 100644 --- a/apps/fz_http/lib/fz_http_web/controllers/auth_controller.ex +++ b/apps/fz_http/lib/fz_http_web/controllers/auth_controller.ex @@ -5,6 +5,7 @@ defmodule FzHttpWeb.AuthController do use FzHttpWeb, :controller require Logger + alias FzCommon.FzCrypto alias FzHttp.Users alias FzHttpWeb.Authentication alias FzHttpWeb.Router.Helpers, as: Routes @@ -128,6 +129,21 @@ defmodule FzHttpWeb.AuthController do end end + def redirect_oidc_auth_uri(conn, %{"provider" => provider}) do + openid_connect = Application.fetch_env!(:fz_http, :openid_connect) + + params = %{ + state: FzCrypto.rand_string(), + # needed for google + access_type: "offline" + } + + uri = openid_connect.authorization_uri(String.to_atom(provider), params) + + conn + |> redirect(external: uri) + end + defp maybe_sign_in(conn, user, %{provider: provider} = auth) when provider in [:identity, :magic_link] do if Application.fetch_env!(:fz_http, :local_auth_enabled) do diff --git a/apps/fz_http/lib/fz_http_web/controllers/root_controller.ex b/apps/fz_http/lib/fz_http_web/controllers/root_controller.ex index 7a4272793..41907e38b 100644 --- a/apps/fz_http/lib/fz_http_web/controllers/root_controller.ex +++ b/apps/fz_http/lib/fz_http_web/controllers/root_controller.ex @@ -11,8 +11,7 @@ defmodule FzHttpWeb.RootController do okta_enabled: conf(:okta_auth_enabled), google_enabled: conf(:google_auth_enabled), local_enabled: conf(:local_auth_enabled), - openid_connect_providers: conf(:openid_connect_providers), - openid_connect: conf(:openid_connect) + openid_connect_providers: conf(:openid_connect_providers) ) end diff --git a/apps/fz_http/lib/fz_http_web/router.ex b/apps/fz_http/lib/fz_http_web/router.ex index 5c1d33f45..5536d5266 100644 --- a/apps/fz_http/lib/fz_http_web/router.ex +++ b/apps/fz_http/lib/fz_http_web/router.ex @@ -61,6 +61,7 @@ defmodule FzHttpWeb.Router do get "/:provider/callback", AuthController, :callback post "/:provider/callback", AuthController, :callback get "/oidc/:provider/callback", AuthController, :callback, as: :auth_oidc + get "/oidc/:provider", AuthController, :redirect_oidc_auth_uri, as: :auth_oidc end # Unauthenticated routes diff --git a/apps/fz_http/lib/fz_http_web/templates/root/auth.html.heex b/apps/fz_http/lib/fz_http_web/templates/root/auth.html.heex index 5caeb9122..328aadf6d 100644 --- a/apps/fz_http/lib/fz_http_web/templates/root/auth.html.heex +++ b/apps/fz_http/lib/fz_http_web/templates/root/auth.html.heex @@ -9,9 +9,10 @@ <%= for {provider, config} <- @openid_connect_providers do %>

- <%= link( + <%= + link( "Sign in with #{config[:label]}", - to: authorization_uri(@openid_connect, provider), + to: Routes.auth_oidc_path(@conn, :redirect_oidc_auth_uri, provider), class: "button") %>

<% end %> diff --git a/apps/fz_http/lib/fz_http_web/views/root_view.ex b/apps/fz_http/lib/fz_http_web/views/root_view.ex index 7d9bce84c..4d7a3751a 100644 --- a/apps/fz_http/lib/fz_http_web/views/root_view.ex +++ b/apps/fz_http/lib/fz_http_web/views/root_view.ex @@ -1,15 +1,3 @@ defmodule FzHttpWeb.RootView do use FzHttpWeb, :view - - alias FzCommon.FzCrypto - - def authorization_uri(oidc, provider) do - params = %{ - state: FzCrypto.rand_string(), - # needed for google - access_type: "offline" - } - - oidc.authorization_uri(provider, params) - end end diff --git a/apps/fz_http/test/fz_http_web/controllers/auth_controller_test.exs b/apps/fz_http/test/fz_http_web/controllers/auth_controller_test.exs index e065b72a3..fd5391c8e 100644 --- a/apps/fz_http/test/fz_http_web/controllers/auth_controller_test.exs +++ b/apps/fz_http/test/fz_http_web/controllers/auth_controller_test.exs @@ -189,4 +189,20 @@ defmodule FzHttpWeb.AuthControllerTest do assert text_response(test_conn, 401) == "Local auth disabled" end end + + describe "oidc signin url" do + @oidc_auth_uri "https://auth.url" + + test "redirects to oidc auth uri", %{unauthed_conn: conn} do + expect(OpenIDConnect.Mock, :authorization_uri, fn provider, _ -> + case provider do + :google -> @oidc_auth_uri + end + end) + + test_conn = get(conn, Routes.auth_oidc_path(conn, :redirect_oidc_auth_uri, "google")) + + assert redirected_to(test_conn) == @oidc_auth_uri + end + end end diff --git a/docs/docs/authenticate/index.md b/docs/docs/authenticate/index.md index ea82cb464..3dbdf45d7 100644 --- a/docs/docs/authenticate/index.md +++ b/docs/docs/authenticate/index.md @@ -75,6 +75,17 @@ to obtain from your OIDC provider. This should be set to `openid email profile` or `openid email profile offline_access` depending on the provider. 1. `label`: The button label text that shows up on your Firezone login screen. +### Pretty URLs + +For each OIDC provider a corresponding pretty URL is created for redirecting to +the configured provider's sign-in URL. For the example OIDC config above, the +URLs are: + +* `https://firezone.example.com/auth/oidc/google` +* `https://firezone.example.com/auth/oidc/okta` + +### Common Providers + We've included instructions on how to set up Firezone with several popular identity providers: