Last active
January 28, 2020 03:45
-
-
Save pgaskin/29fff1f8fce3e85bf4e5dbd5d3c20f0f to your computer and use it in GitHub Desktop.
Improved loginsrv template. https://sso.geek1011.net.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {{- /* Template config options */ -}} | |
| {{- /* $internal_group, if set, will show $internal_group_msg to all users not in the specified group. */ -}} | |
| {{- $internal_group := "internal" -}} | |
| {{- /* internal_group_msg shows for users who are not in $internal_group */ -}} | |
| {{- $internal_group_msg := "You are logged in as an external user, and may not have access to all resources." -}} | |
| {{- /* End template config options */ -}} | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <meta http-equiv="X-UA-Compatible" content="ie=edge"/> | |
| <title>SSO</title> | |
| <link href="https://fonts.googleapis.com/css?family=PT+Sans:400,700&display=swap" rel="stylesheet"> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, body { | |
| margin: 0; | |
| padding: 0; | |
| background: #fafafa; | |
| } | |
| body { | |
| font-size: 16px; | |
| font-family: 'PT Sans', Roboto, -apple-system, Tahoma, sans-serif; | |
| margin: 0 32px; | |
| line-height: 1.45; | |
| } | |
| @media screen and (min-width: 600px) { | |
| body { | |
| margin: 0 64px; | |
| } | |
| } | |
| h1, h2, h3, h4, h5, h6 { | |
| margin: 0; | |
| padding: 0; | |
| line-height: inherit; | |
| font-weight: normal; | |
| font-style: normal; | |
| } | |
| .global-nav { | |
| display: flex; | |
| flex-direction: row; | |
| align-items: flex-start; | |
| justify-content: flex-start; | |
| position: relative; | |
| font-size: 14px; | |
| } | |
| .global-nav__link, | |
| .global-nav__link:link, | |
| .global-nav__link:visited { | |
| display: block; | |
| background: #000; | |
| color: #fff; | |
| text-decoration: none; | |
| padding: 4px 8px; | |
| transition: all .15s ease-in-out; | |
| } | |
| .global-nav__link:hover { | |
| background: #222; | |
| } | |
| .login { | |
| max-width: 500px; | |
| } | |
| .login__header { | |
| margin: 16px 0; | |
| } | |
| .login__header h1 { | |
| font-size: 36px; | |
| font-weight: 700; | |
| } | |
| .login__header h2 { | |
| font-size: 18px; | |
| font-weight: 400; | |
| } | |
| .login__form { | |
| display: block; | |
| } | |
| .login__form__field { | |
| display: block; | |
| margin: 8px 0; | |
| } | |
| .login__form__field--buttons { | |
| margin-top: 16px; | |
| margin-bottom: 16px; | |
| } | |
| .login__form__field label { | |
| display: block; | |
| font-size: 11px; | |
| margin-bottom: 2px; | |
| } | |
| .login__form__field input[type="text"], | |
| .login__form__field input[type="password"] { | |
| display: block; | |
| width: 100%; | |
| max-width: 100%; | |
| padding: 8px; | |
| margin: 0; | |
| font-size: inherit; | |
| background: #f2f2f2; | |
| color: #000; | |
| border: 1px solid #ccc; | |
| border-radius: 3px; | |
| outline: 0; | |
| transition: all .15s ease-in-out; | |
| font-family: inherit; | |
| } | |
| .login__form__field input[type="text"]:hover, | |
| .login__form__field input[type="password"]:hover { | |
| border-color: #aaa; | |
| } | |
| .login__form__field input[type="text"]:focus, | |
| .login__form__field input[type="password"]:focus { | |
| background: #fff; | |
| border-color: rgb(0, 110, 255); | |
| } | |
| .login__form__field input[type="submit"] { | |
| display: inline-block; | |
| padding: 4px 8px; | |
| background: rgb(0, 93, 214); | |
| color: #fff; | |
| border: 1px solid rgba(0, 0, 0, 0.3); | |
| border-radius: 3px; | |
| outline: 0; | |
| transition: all .15s ease-in-out; | |
| } | |
| .login__form__field input[type="submit"]:hover { | |
| background: rgb(0, 75, 173); | |
| } | |
| .login__form__field input[type="submit"]:active { | |
| background: rgb(0, 63, 146); | |
| } | |
| .login__form__field input[type="submit"]:focus { | |
| border: 1px solid rgba(0, 0, 0, 0.6); | |
| } | |
| .login__form__field input[type="submit"]::-moz-focus-inner { | |
| border: 0; | |
| } | |
| .login__form__oauth { | |
| display: block; | |
| margin: 16px 0; | |
| } | |
| .login__form__oauth__title { | |
| display: block; | |
| font-size: 14px; | |
| margin-bottom: 8px; | |
| font-weight: 700; | |
| } | |
| .login__form__oauth__button, | |
| .login__form__oauth__button:link, | |
| .login__form__oauth__button:visited { | |
| display: inline-block; | |
| padding: 4px 8px; | |
| background: #eee; | |
| border: 1px solid #ccc; | |
| border-radius: 3px; | |
| text-align: center; | |
| text-decoration: none; | |
| color: inherit; | |
| outline: 0; | |
| margin-right: 16px; | |
| transition: all .15s ease-in-out; | |
| } | |
| .login__form__oauth__button:hover { | |
| background: #e3e3e3; | |
| border: 1px solid #aaa; | |
| } | |
| .login__form__oauth__button:focus { | |
| border: 1px solid #aaa; | |
| } | |
| .login__form__oauth__button:active { | |
| background: #dedede; | |
| } | |
| .login__form__oauth__button__icon { | |
| display: block; | |
| height: 32px; | |
| height: 32px; | |
| object-fit: contain; | |
| object-position: center; | |
| margin: 4px auto; | |
| } | |
| .login__form__oauth__button__label { | |
| display: block; | |
| font-size: 12px; | |
| } | |
| .login__error { | |
| display: block; | |
| background: rgb(250, 168, 175); | |
| border: 1px solid rgb(230, 99, 110); | |
| border-radius: 3px; | |
| padding: 8px; | |
| margin-top: 16px; | |
| margin-bottom: 16px; | |
| } | |
| .login__info__card { | |
| display: flex; | |
| flex-direction: row; | |
| align-items: flex-start; | |
| justify-content: flex-start; | |
| padding: 8px; | |
| background: #eee; | |
| border: 1px solid #ccc; | |
| border-radius: 3px; | |
| margin: 8px 0; | |
| } | |
| .login__info__card__picture { | |
| display: block; | |
| flex: 0 0 64px; | |
| height: 64px; | |
| width: 64px; | |
| margin-right: 16px; | |
| object-fit: contain; | |
| object-position: center; | |
| } | |
| .login__info__card__info { | |
| display: block; | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .login__info__card__info__title { | |
| display: block; | |
| font-weight: 700; | |
| font-size: 18px; | |
| } | |
| .login__info__card__info__field { | |
| display: block; | |
| } | |
| .login__info__expiry { | |
| display: block; | |
| font-size: 14px; | |
| color: #666; | |
| } | |
| .login__debug { | |
| display: block; | |
| margin-top: 8px; | |
| font-size: 12px; | |
| color: #999; | |
| } | |
| .global-nav, | |
| .login__header, | |
| .login__form__field label, | |
| .login__form__oauth, | |
| .login__error, | |
| .login__info__expiry { | |
| -webkit-user-select: none; | |
| -webkit-user-drag: none; | |
| -moz-user-select: none; | |
| -ms-user-select: none; | |
| user-select: none; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <nav class="global-nav"> | |
| <a href="#" class="global-nav__link"></a> | |
| </nav> | |
| <main class="login"> | |
| <header class="login__header"> | |
| <h1> | |
| {{- if not .Authenticated -}} | |
| Log In | |
| {{- else -}} | |
| SSO | |
| {{- end -}} | |
| </h1> | |
| <h2> | |
| {{- if not .Authenticated -}} | |
| Please log in using your SSO credentials. | |
| {{- else -}} | |
| You are currently logged in. | |
| {{- end -}} | |
| </h2> | |
| </header> | |
| {{- if .Error}} | |
| <aside class="login__error"> | |
| Internal server error. Please try again later. | |
| </div> | |
| {{- end}} | |
| <aside class="login__error logout" style="display: none;"> | |
| You have been successfully logged out. | |
| </aside> | |
| {{- if .Failure}} | |
| <aside class="login__error"> | |
| The username or password you provided was incorrect. | |
| </aside> | |
| {{- end}} | |
| {{if not .Authenticated -}} | |
| <section class="login__form"> | |
| {{if .Config.Backends -}} | |
| <form action="{{.Config.LoginPath}}" method="post"> | |
| <div class="login__form__field"> | |
| <label for="username">Username</label> | |
| <input type="text" name="username" id="username" placeholder="Username" autocomplete="username" {{with .UserInfo.Sub -}} value="{{.}}" {{- else -}} autofocus="" {{- end}}/> | |
| </div> | |
| <div class="login__form__field"> | |
| <label for="username">Password</label> | |
| <input type="password" name="password" id="password" placeholder="Password" autocomplete="current-password" {{if .UserInfo.Sub -}} autofocus="" {{- end}}/> | |
| </div> | |
| <div class="login__form__field login__form__field--buttons"> | |
| <input type="submit" value="Log In"/> | |
| </div> | |
| </form> | |
| {{- end}} | |
| {{- if .Config.Oauth -}} | |
| <div class="login__form__oauth"> | |
| <div class="login__form__oauth__title">{{if and .Config.Backends .Config.Oauth}}Or, s{{else}}S{{end}}ign in with:</div> | |
| {{range $p, $o := .Config.Oauth -}} | |
| {{- $pp := (printf "%s/%s" $.Config.LoginPath $p) -}} | |
| {{- if eq $.Config.LoginPath "/" -}} | |
| {{- $pp = (printf "/%s" $p) -}} | |
| {{- end -}} | |
| {{- $pn := (ucfirst $p) -}} | |
| {{- if eq $p "github" -}} | |
| {{- $pn = "GitHub" -}} | |
| {{- end -}} | |
| <a href="{{$pp}}" class="login__form__oauth__button" title="{{$pn}}"> | |
| <img src="https://cdn.jsdelivr.net/npm/simple-icons@2.3.0/icons/{{$p}}.svg" alt="{{$pn}}" class="login__form__oauth__button__icon"/> | |
| <div class="login__form__oauth__button__label">{{$pn}}</div> | |
| </a> | |
| {{- end}} | |
| </div> | |
| {{- end -}} | |
| {{if and (not .Config.Backends) (not .Config.Oauth) -}} | |
| No authentication methods available. | |
| {{- end}} | |
| </section> | |
| {{- else -}} | |
| {{- if $internal_group -}} | |
| {{- $is_internal := "" -}} | |
| {{- range $i, $g := .UserInfo.Groups -}} | |
| {{- if eq $g $internal_group -}} | |
| {{- $is_internal = "yes" -}} | |
| {{- end -}} | |
| {{- end -}} | |
| {{- if not $is_internal -}}<aside class="login__error">{{$internal_group_msg}}</aside>{{- end -}} | |
| {{end -}} | |
| <section class="login__info"> | |
| {{with .UserInfo -}} | |
| <div class="login__info__card"> | |
| <img class="login__info__card__picture" src="{{with .Picture}}{{.}}{{else}}data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64' version='1'%3E%3Ccircle style='opacity:0.2;fill:%2300100f' cx='32' cy='33' r='28'/%3E%3Ccircle style='fill:%23009587' cx='32' cy='32' r='28'/%3E%3Cg style='opacity:0.2' transform='translate(0,1)'%3E%3Cpath d='m 32,14 c -3.8668,0 -7,3.1346 -7,7 0,3.8654 3.1332,7 7,7 3.8668,0 7,-3.1346 7,-7 0,-3.8654 -3.1332,-7 -7,-7 z'/%3E%3Cpath d='m 32,33.000002 c -13.9986,0.0084 -14,8.861538 -14,8.861538 v 3.6 c 0,0 2.584598,5.53846 14,5.53846 11.415402,0 14,-5.53846 14,-5.53846 v -3.6 c 0,0 0,-8.867076 -13.9972,-8.861538 z'/%3E%3C/g%3E%3Cg%3E%3Cpath style='fill:%23ffffff' d='m 32,14 c -3.8668,0 -7,3.1346 -7,7 0,3.8654 3.1332,7 7,7 3.8668,0 7,-3.1346 7,-7 0,-3.8654 -3.1332,-7 -7,-7 z'/%3E%3Cpath style='fill:%23ffffff' d='m 32,33.000002 c -13.9986,0.0084 -14,8.861538 -14,8.861538 v 3.6 c 0,0 2.584598,5.53846 14,5.53846 11.415402,0 14,-5.53846 14,-5.53846 v -3.6 c 0,0 0,-8.867076 -13.9972,-8.861538 z'/%3E%3C/g%3E%3Cpath style='opacity:0.2;fill:%23ffffff' d='M 32 4 A 28 28 0 0 0 4 32 A 28 28 0 0 0 4.0175781 32.492188 A 28 28 0 0 1 32 5 A 28 28 0 0 1 59.974609 32.492188 A 28 28 0 0 0 60 32 A 28 28 0 0 0 32 4 z'/%3E%3C/svg%3E{{end}}" alt=""/> | |
| <div class="login__info__card__info"> | |
| {{if not .Name -}} | |
| <div class="login__info__card__info__title">{{.Sub}}</div> | |
| {{- else -}} | |
| <div class="login__info__card__info__title">{{.Name}}</div> | |
| <div class="login__info__card__info__field"><b>Username:</b> {{.Sub}}</div> | |
| {{- end}} | |
| {{with .Email}}<div class="login__info__card__info__field"><b>Email:</b> {{.}}</div>{{end}} | |
| {{with .Domain}}<div class="login__info__card__info__field"><b>Domain:</b> {{.}}</div>{{end}} | |
| {{with .Groups}}<div class="login__info__card__info__field"><b>Groups:</b> {{range $i, $g := .}}{{if $i}}, {{end}}{{$g}}{{end}}</div>{{end}} | |
| </div> | |
| </div> | |
| {{if .Expiry -}} | |
| <div class="login__info__expiry"> | |
| Login expires at <span class="unix">{{.Expiry}}</span>{{with .Refreshes}}, with {{.}} refreshes remaining.{{end}}. | |
| </div> | |
| {{- end}} | |
| {{- end}} | |
| <form action="{{.Config.LoginPath}}" method="get"> | |
| <div class="login__form__field login__form__field--buttons"> | |
| <input type="hidden" name="logout" value="true"/> | |
| <input type="submit" value="Log Out"> | |
| </div> | |
| </form> | |
| </section> | |
| {{- end}} | |
| <aside class="login__debug"> | |
| Cookie: {{.Config.CookieName}}{{if .Config.CookieSecure}}, HTTPS only{{end}}{{if .Config.CookieHTTPOnly}}, server-side auth only{{end}}. | |
| </aside> | |
| </main> | |
| <script> | |
| document.title = window.location.host; | |
| document.querySelector(".global-nav__link").href = "//" + window.location.host; | |
| document.querySelector(".global-nav__link").innerHTML = window.location.hostname; | |
| for (const el of document.querySelectorAll(".unix")) | |
| el.innerHTML = new Date(parseInt(el.innerHTML.trim(), 10) * 1000).toLocaleString(); | |
| const params = new URLSearchParams(window.location.search); | |
| if (params.get("logout") == "true") { | |
| document.querySelector(".logout").style.display = "block"; | |
| const backTo = params.get("backTo"); | |
| if (backTo && backTo != "") | |
| window.setTimeout(() => window.location = backTo, 2000); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment