Skip to content

Instantly share code, notes, and snippets.

@pgaskin
Last active January 28, 2020 03:45
Show Gist options
  • Select an option

  • Save pgaskin/29fff1f8fce3e85bf4e5dbd5d3c20f0f to your computer and use it in GitHub Desktop.

Select an option

Save pgaskin/29fff1f8fce3e85bf4e5dbd5d3c20f0f to your computer and use it in GitHub Desktop.
Improved loginsrv template. https://sso.geek1011.net.
{{- /* 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