Skip to content

Commit

Permalink
Add Brandable Dialogs (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
spjmurray authored Mar 22, 2024
1 parent 9388737 commit 71da5c4
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 96 deletions.
4 changes: 2 additions & 2 deletions charts/identity/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Helm chart for deploying Unikorn's IdP

type: application

version: v0.1.15
appVersion: v0.1.15
version: v0.1.16
appVersion: v0.1.16

icon: https://raw.githubusercontent.com/unikorn-cloud/assets/main/images/logos/dark-on-light/icon.png
8 changes: 8 additions & 0 deletions charts/identity/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ spec:
args:
- --namespace={{ .Release.Namespace }}
- --host=https://{{ .Values.host }}
{{- with $branding := .Values.branding }}
{{- if $branding.loginRedirectURL }}
{{ printf "- --login-redirect-url=%s" $branding.loginRedirectURL | nindent 8 }}
{{- end }}
{{- if $branding.errorRedirectURL }}
{{ printf "- --error-redirect-url=%s" $branding.errorRedirectURL | nindent 8 }}
{{- end }}
{{- end }}
{{- with $cors := .Values.cors }}
{{- range $origin := $cors.allowOrigin }}
{{ printf "- --cors-allow-origin=%s" $origin | nindent 8 }}
Expand Down
6 changes: 6 additions & 0 deletions charts/identity/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ image: ~
# oauth2 issuer etc.
host: identity.acme.org

# Branding options allow you to "white-box" and apply your own spin on the
# login and error pages.
# branding:
# loginRedirectURL: https://my-host/login
# errorRedirectURL: https://my-host/error

# A static list of registered client applications.
# clients:
# - # Must be a valid Kubernetes resource name.
Expand Down
12 changes: 4 additions & 8 deletions openapi/server.spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,7 @@ components:
description: Login request options.
type: object
required:
- provider
- query
- state
properties:
email:
description: The user's email address.
Expand All @@ -463,12 +462,9 @@ components:
provider:
description: The explcit provider type.
type: string
enum:
- dynamic
- google
- microsoft
query:
description: The query string supplied to the authorization endpoint.
nullable: true
state:
description: The state string supplied by the authorization endpoint.
type: string
tokenRequestOptions:
description: oauth2 token endpoint.
Expand Down
110 changes: 55 additions & 55 deletions pkg/generated/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 3 additions & 13 deletions pkg/generated/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 39 additions & 14 deletions pkg/oauth2/federated.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"github.com/coreos/go-oidc/v3/oidc"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/spf13/pflag"
"golang.org/x/oauth2"

"github.com/unikorn-cloud/core/pkg/server/errors"
Expand All @@ -50,6 +51,13 @@ import (
)

type Options struct {
loginRedirectURL string
errorRedirectURL string
}

func (o *Options) AddFlags(f *pflag.FlagSet) {
f.StringVar(&o.loginRedirectURL, "login-redirect-url", "", "External page to handle login requests")
f.StringVar(&o.errorRedirectURL, "error-redirect-url", "", "External page to handle errors")
}

// Authenticator provides Keystone authentication functionality.
Expand Down Expand Up @@ -384,14 +392,26 @@ func (a *Authenticator) Authorization(w http.ResponseWriter, r *http.Request) {
}
}

loginQuery := url.Values{}

loginQuery.Set("state", query.Encode())
loginQuery.Set("callback", "https://"+r.Host+"/oauth2/v2/login")

// Redirect to an external login handler, if you have chosen to.
if a.options.loginRedirectURL != "" {
http.Redirect(w, r, fmt.Sprintf("%s?%s", a.options.loginRedirectURL, loginQuery.Encode()), http.StatusFound)
return
}

// Otherwise use the internal version.
tmpl, err := template.New("login").Parse(loginTemplate)
if err != nil {
log.Info("oauth2: failed to parse template", "error", err)
return
}

templateContext := map[string]interface{}{
"query": query.Encode(),
"state": query.Encode(),
}

var buffer bytes.Buffer
Expand Down Expand Up @@ -566,27 +586,18 @@ func (a *Authenticator) Login(w http.ResponseWriter, r *http.Request) {
return
}

if !r.Form.Has("email") {
log.Info("email doesn't exist in form")
return
}

if !r.Form.Has("query") {
log.Info("query doesn't exist in form")
if !r.Form.Has("state") {
log.Info("state doesn't exist in form")
return
}

if !r.Form.Has("provider") {
log.Info("provider doesn't exist in form")
}

query, err := url.ParseQuery(r.Form.Get("query"))
query, err := url.ParseQuery(r.Form.Get("state"))
if err != nil {
log.Error(err, "failed to parse query")
return
}

if providerType := r.Form.Get("provider"); providerType != "dynamic" {
if providerType := r.Form.Get("provider"); providerType != "" {
provider, err := a.lookupProviderByType(r.Context(), unikornv1.IdentityProviderType(providerType))
if err != nil {
authorizationError(w, r, query.Get("redirect_uri"), ErrorServerError, err.Error())
Expand All @@ -608,6 +619,20 @@ func (a *Authenticator) Login(w http.ResponseWriter, r *http.Request) {
return
}

// Remove the cookie otherwise.
cookie := &http.Cookie{
Name: ProviderCookie,
Value: "undefined",
MaxAge: -1,
}

w.Header().Add("Set-Cookie", cookie.String())

if !r.Form.Has("email") {
log.Info("email doesn't exist in form")
return
}

organization, err := a.lookupOrganization(r.Context(), r.Form.Get("email"))
if err != nil {
authorizationError(w, r, query.Get("redirect_uri"), ErrorServerError, err.Error())
Expand Down
6 changes: 2 additions & 4 deletions pkg/oauth2/login.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@
function submitWithProvider(provider) {
const providerInput = document.getElementById('provider');
providerInput.value = provider;
console.log(providerInput);

const form = document.getElementById('form');
console.log(form);
form.submit();
}
</script>
Expand All @@ -87,10 +85,10 @@
<main>
<form id="form" method="post" action="/oauth2/v2/login">
<!-- Use this to hold state across the dialog -->
<input id="query" name="query" type="hidden" value="{{ .query }}" />
<input id="state" name="state" type="hidden" value="{{ .state }}" />

<!-- Use this to cummuncate the provider to use -->
<input id="provider" name="provider" type="hidden" value="dynamic"/>
<input id="provider" name="provider" type="hidden" value=""/>

<section>
<p>Enter your e-mail address to continue if using a domain login</p>
Expand Down
1 change: 1 addition & 0 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func (s *Server) AddFlags(goflags *flag.FlagSet, flags *pflag.FlagSet) {
s.Options.AddFlags(flags)
s.HandlerOptions.AddFlags(flags)
s.JoseOptions.AddFlags(flags)
s.OAuth2Options.AddFlags(flags)
s.CORSOptions.AddFlags(flags)
}

Expand Down

0 comments on commit 71da5c4

Please sign in to comment.