oauth3.org is now its own thing
This commit is contained in:
commit
3327521bd3
|
@ -0,0 +1 @@
|
|||
*.*sw*
|
|
@ -0,0 +1 @@
|
|||
../assets/org.oauth3/.well-known/oauth3
|
|
@ -0,0 +1,3 @@
|
|||
This is taken from parts of org.oauth3-frontend and oauth3.js
|
||||
|
||||
Needs a proper README. TODO cc / @coolaj86
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>authNoCode</title>
|
||||
</head>
|
||||
<body>
|
||||
Trouble shooting steps to get the code
|
||||
</body>
|
||||
<script src=""></script>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>authNoCode</title>
|
||||
</head>
|
||||
<body>
|
||||
Explanation for no password
|
||||
</body>
|
||||
<script src=""></script>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
.dap-main {
|
||||
background-color: #add8e6;
|
||||
}
|
||||
.dap-logo {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
.mock-main {
|
||||
background-color: #98fb98;
|
||||
}
|
||||
|
||||
.js-provider-logo {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
.dap-centered-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dap-centered-div {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dap-space-on-top {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.js-remember-label {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dap-scrunch-bottom {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.dap-scrunch-top {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.dap-scrunch-both {
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.js-remember-checkbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.js-auth-checkbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dap-bordered {
|
||||
margin: 0 auto;
|
||||
width: 400px;
|
||||
padding: 20px 20px 5px 20px;
|
||||
border-top: 3px solid #6D99ed;
|
||||
border-bottom: 3px solid #5C6FE0;
|
||||
background-image: linear-gradient(#6D99ed, #5C6FE0),
|
||||
linear-gradient(#6D99ed, #5C6FE0);
|
||||
background-size: 3px 100%;
|
||||
background-position: 0 0, 100% 0;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.dap-normal-text {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.dap-med-text {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.dap-small-text {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 14px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.dap-purple-text {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 18px;
|
||||
color: #7464ed;
|
||||
}
|
||||
|
||||
.dap-help-text {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 14px;
|
||||
text-decoration: underline;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dap-input {
|
||||
height: 50px;
|
||||
width: 350px;
|
||||
margin: 0 6% 0 6%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.dap-input::-webkit-input-placeholder {
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dap-full-button-green {
|
||||
background-image: -webkit-linear-gradient(top, #00C267, #22A05C);
|
||||
height: 52px;
|
||||
width: 356px;
|
||||
box-shadow: 0 0 8px #ccc;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
margin: 10px 6% 0 6%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dap-full-button-pink {
|
||||
background-image: -webkit-linear-gradient(top, #FF5C5C, #E54043);
|
||||
height: 52px;
|
||||
width: 356px;
|
||||
box-shadow: 0 0 8px #ccc;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
margin: 10px 6% 0 6%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dap-full-button-purple {
|
||||
background-image: -webkit-linear-gradient(top, #6d99ed, #5C6FE0);
|
||||
height: 52px;
|
||||
width: 356px;
|
||||
box-shadow: 0 0 8px #ccc;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
margin: 10px 6% 0 6%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dap-3-4-button-green {
|
||||
background-image: -webkit-linear-gradient(top, #93d89c, #39a04a);
|
||||
height: 52px;
|
||||
width: 238px;
|
||||
box-shadow: 0 0 8px #ccc;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
margin: 10px 2% 0 2%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dap-1-4-button-purple {
|
||||
background-image: -webkit-linear-gradient(top, #6d99ed, #5C6FE0);
|
||||
height: 52px;
|
||||
width: 119px;
|
||||
box-shadow: 0 0 8px #ccc;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
margin: 10px 2% 0 2%;
|
||||
text-align: center;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dap-3-4-span {
|
||||
float: left;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
.dap-1-4-span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dap-social-media {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
width: 330px;
|
||||
margin: 0 5% 0 5%;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.fa-gray {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.fa-purple {
|
||||
color: #5C6FE0;
|
||||
}
|
||||
|
||||
.icon-centered-3x {
|
||||
margin: 0 162px 0 162px;
|
||||
}
|
||||
|
||||
.dap-user-plus-app {
|
||||
width: 300px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dap-user-plus-app > .fa-gray {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.dap-app-auth-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dap-app-auth-list > li {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fa-square-o > span {
|
||||
margin-left: 12px !important;
|
||||
}
|
||||
|
||||
.dap-remember-margin {
|
||||
margin-right: 7px !important;
|
||||
}
|
||||
|
||||
.dap-remember-me {
|
||||
margin-top: 7px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.dap-app-auth-list > li > span {
|
||||
margin-top: 4px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dap-li-disabled {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/* --------------- Line Around Effect ----------- */
|
||||
.dap-line-around {
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
color: #777;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dap-line-around:before, .dap-line-around:after {
|
||||
background-color: #ccc;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 1px;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
width: 41%;
|
||||
}
|
||||
|
||||
.dap-line-around:before {
|
||||
right: .5em;
|
||||
margin-left: -50%;
|
||||
}
|
||||
|
||||
.dap-line-around:after {
|
||||
left: .5em;
|
||||
margin-right: -50%;
|
||||
}
|
||||
/* ------------------------------------------------ */
|
||||
|
||||
.noselect {
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently
|
||||
supported by Chrome and Opera */
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.dap-lab-logo {
|
||||
height: 78px;
|
||||
width: auto;
|
||||
border-radius: 50px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 640 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Login Facilitator: OAuth3.org</title>
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Lato:300">
|
||||
<script src="https://use.fontawesome.com/3af0faae66.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="fade mock-main">
|
||||
|
||||
<!-- STEP 1: ask the user where they want to log in -->
|
||||
<!-- STEP 2: ask the user for their email -->
|
||||
<!-- STEP 3+4: ask for login code and to remember device -->
|
||||
<!-- TODO: remember-me-not implementation? -->
|
||||
|
||||
<!-- <button class="btn btn-secondary js-authz-show js-authz-remember-me-not">Just this once</button>-->
|
||||
|
||||
<!-- Step 5: ask for permissions -->
|
||||
|
||||
<div class="dap-bordered js-userid-container" style="display: none;">
|
||||
<p class="dap-centered-text dap-normal-text">Please, sign in to Daplie Labs...</p>
|
||||
<form method="post" action="">
|
||||
<input type="email" class="dap-input js-oauth3-email emailInput" placeholder="Input your e-mail"></input>
|
||||
<button class="dap-full-button-green js-authn-show" disabled>CONTINUE</button>
|
||||
</form>
|
||||
<p class="dap-line-around">or</p>
|
||||
<div class="dap-social-media dap-normal-text">
|
||||
<span class="fa fa-2x fa-gray fa-facebook-square js-facebook-login"></span>
|
||||
<span class="fa fa-2x fa-gray fa-twitter-square js-twitter-login"></span>
|
||||
<span class="fa fa-2x fa-gray fa-google-plus-square js-google-login"></span>
|
||||
<span class="fa fa-2x fa-gray fa-github-square js-github-login"></span>
|
||||
<span class="fa fa-2x fa-gray fa-plus-square js-gitlab-login"></span>
|
||||
</div>
|
||||
<br>
|
||||
<a href="./loginwhatis.html" target="_blank"><p class="dap-centered-text dap-help-text">What is this?</p></a>
|
||||
</div>
|
||||
|
||||
<div class="dap-bordered js-authn">
|
||||
<div class="dap-normal-text">
|
||||
<span class="fa fa-3x icon-centered-3x fa-purple fa-envelope"></span>
|
||||
</div>
|
||||
<p class="dap-centered-text dap-scrunch-top dap-normal-text">A special sign-in code was sent to:</p>
|
||||
<p class="dap-centered-text dap-scrunch-both dap-purple-text"><span class="js-user-email"> </span></p>
|
||||
<p class="dap-centered-text dap-scrunch-bottom dap-med-text">Please enter the code below:</p>
|
||||
<form method="post" onsubmit="">
|
||||
<input type="hidden" class="js-authn-otp-uuid">
|
||||
<input class="dap-input js-authn-otp-code" placeholder="XXXX-XXXX-XXXX"></input>
|
||||
<div class="dap-centered-div dap-space-on-top">
|
||||
<label class="js-remember-label dap-normal-text">
|
||||
<span class="fa fa-2x fa-purple fa-square-o dap-remember-margin js-remember-status"></span>
|
||||
<span class="dap-remember-me noselect">Remember this device.</span>
|
||||
<input class="js-remember-checkbox" type="checkbox" checked="false"></input>
|
||||
</label>
|
||||
</div>
|
||||
<button class="dap-full-button-green js-remember-btn js-authz-remember-me">SIGN IN ONCE</button>
|
||||
</form>
|
||||
<a href="./authnocode.html" target="_blank">
|
||||
<p class="dap-centered-text dap-help-text">I didn't receive my code...</p>
|
||||
</a>
|
||||
<a href="./authnopass.html" target="_blank">
|
||||
<p class="dap-centered-text dap-help-text">Why am I not using a password?</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="dap-bordered dap-normal-text js-authz">
|
||||
<br>
|
||||
<div class="dap-user-plus-app">
|
||||
<span class="fa fa-3x fa-purple fa-user-circle"></span>
|
||||
<span class="fa fa-2x fa-gray fa-plus"></span>
|
||||
<img class="dap-lab-logo" src="./img/Daplie-Badge-Purple.png" alt="Daplie Labs Logo">
|
||||
</div>
|
||||
<p class="dap-centered-text dap-normal-text"> OK! Almost done. Allow app to...?</p>
|
||||
<br>
|
||||
|
||||
<form class="js-authorization-decision" action="#">
|
||||
<ul class="js-scopes-container dap-app-auth-list">
|
||||
<li class="checkbox fa fa-check-square-o dap-purple-text js-auth-li-enabled">
|
||||
<span class="dap-small-text js-scope-desc noselect"> </span>
|
||||
<input class="checkbox js-scope-toggle js-auth-checkbox" type="checkbox">
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<button class="dap-full-button-green js-login-allow" type="button">AUTHORIZE THIS APP</button>
|
||||
<button class="dap-full-button-pink js-login-deny" type="button">DENY THIS APP</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- TODO: Remove Inline Style - Hidden until added into process -->
|
||||
<div style="display: none" class="dap-bordered dap-normal-text">
|
||||
<br>
|
||||
<div class="dap-user-plus-app">
|
||||
<span class="fa fa-3x fa-purple fa-user-circle"></span>
|
||||
<span class="fa fa-2x fa-gray fa-plus"></span>
|
||||
<span class="fa fa-3x fa-purple fa-laptop"></span>
|
||||
</div>
|
||||
<p class="dap-centered-text dap-scrunch-top dap-normal-text">It looks like your user agent is</p>
|
||||
<p><span class="js-sniffed-device"></span></p>
|
||||
<p class="dap-centered-text dap-scrunch-bottom dap-med-text">How long would you like to trust this device?</p>
|
||||
<button class="dap-3-4-button-green js-authz-remember-me">FOREVER</button>
|
||||
<button class="dap-1-4-button-purple js-authz-remember-me-not">ONE DAY</button>
|
||||
<span class="dap-help-text dap-3-4-span">Great if you aren't paranoid.</span>
|
||||
<span class="dap-help-text dap-1-4-span">Great if you're paranoid.</span>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p class="dap-centered-text dap-help-text">What is this?</p>
|
||||
</div>
|
||||
|
||||
<div class="dap-bordered dap-normal-text js-logout-container">
|
||||
<p class="dap-centered-text">Sign out of Daplie and all Applications?</p>
|
||||
<button type="button" class="dap-full-button-green js-logout">Sign Out</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if IE]><script src="bower_components/rsvp.js/rsvp.js"></script><![endif]-->
|
||||
<script src="/assets/com.jquery/jquery-3.1.1.js"></script>
|
||||
<script src="./js/mock.js"></script>
|
||||
<script src="./js/script.js"></script>
|
||||
<script src="/assets/org.oauth3/oauth3.core.js"></script>
|
||||
<script src="/assets/org.oauth3/oauth3.issuer.js"></script>
|
||||
<!--script src="/assets/org.oauth3/oauth3.mock.js"></script-->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
mkdir -p assets
|
||||
if [ -d ./assets/org.oauth3 ]; then
|
||||
git clone git@git.daplie.com:Daplie/oauth3.js.git ./assets/org.oauth3
|
||||
fi
|
||||
pushd ./assets/org.oauth3
|
||||
git checkout v1
|
||||
git pull
|
||||
popd
|
||||
bower install rsvp
|
|
@ -0,0 +1,182 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
////////////////////////
|
||||
// //
|
||||
// 3rd Party Logins //
|
||||
// //
|
||||
////////////////////////
|
||||
util.facebookLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var ppid = '';
|
||||
|
||||
var authObj = window.OAUTH3.core.implicitGrant(
|
||||
{ authorization_dialog: { url:'https:////www.facebook.com/v2.8/dialog/oauth' }
|
||||
}
|
||||
, { redirectUri: 'https://' + CONFIG.host + '/.well-known/oauth3/callback.html'
|
||||
, appId: '590912911107527'
|
||||
}
|
||||
);
|
||||
|
||||
var signinW = window.open(
|
||||
authObj.url
|
||||
, "third-party-provider"
|
||||
);
|
||||
|
||||
var callbackName = '--oauth3-callback-' + authObj.state;
|
||||
|
||||
console.log('authobj: ', authObj);
|
||||
console.log('callback: ',callbackName);
|
||||
|
||||
window[callbackName] = function (obj) {
|
||||
console.log('callback obj: ', obj);
|
||||
$.ajax({
|
||||
url: "https://graph.facebook.com/me"
|
||||
, headers: {authorization: "Bearer " + obj.access_token}
|
||||
}).then( function (ajaxObj) {
|
||||
console.log("Ajax obj: ", ajaxObj);
|
||||
ppid = ajaxObj.id;
|
||||
});
|
||||
};
|
||||
};
|
||||
util.twitterLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var authObj = window.OAUTH3.core.implicitGrant(
|
||||
{ authorization_dialog: { url:'https://api.twitter.com/oauth/authorize' }
|
||||
}
|
||||
, { redirectUri: 'https://' + CONFIG.host + '/.well-known/oauth3/callback.html'
|
||||
, appId: 'HJuxVttZUX4kPmbafvzmcuU1O'
|
||||
}
|
||||
);
|
||||
|
||||
var signinW = window.open(
|
||||
authObj.url
|
||||
, "third-party-provider"
|
||||
);
|
||||
|
||||
var callbackName = '--oauth3-callback-' + authObj.state;
|
||||
|
||||
console.log('authobj: ', authObj);
|
||||
console.log('callback: ',callbackName);
|
||||
|
||||
window[callbackName] = function (obj) {
|
||||
console.log('callback obj: ', obj);
|
||||
};
|
||||
};
|
||||
util.googleLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var authObj = window.OAUTH3.core.implicitGrant(
|
||||
{ authorization_dialog: { url:'https://accounts.google.com/o/oauth2/v2/auth' }
|
||||
}
|
||||
, { redirectUri: 'https://' + CONFIG.host + '/.well-known/oauth3/callback.html'
|
||||
, appId: '458817232132-sdk9eioi22k36jqpj0mq3i89h6tsohut.apps.googleusercontent.com'
|
||||
, scope: 'profile'
|
||||
}
|
||||
);
|
||||
|
||||
var signinW = window.open(
|
||||
authObj.url
|
||||
, "third-party-provider"
|
||||
);
|
||||
|
||||
var callbackName = '--oauth3-callback-' + authObj.state;
|
||||
|
||||
console.log('authobj: ', authObj);
|
||||
console.log('callback: ',callbackName);
|
||||
|
||||
window[callbackName] = function (obj) {
|
||||
console.log('callback obj: ', obj);
|
||||
$.ajax({
|
||||
url: "https://www.googleapis.com/oauth2/v3/userinfo"
|
||||
, headers: {authorization: "Bearer " + obj.access_token}
|
||||
}).then( function (ajaxObj) {
|
||||
console.log("Ajax obj: ", ajaxObj);
|
||||
});
|
||||
};
|
||||
};
|
||||
util.githubLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var ppid = '';
|
||||
|
||||
var authObj = window.OAUTH3.core.implicitGrant(
|
||||
{ authorization_dialog: { url:'https://github.com/login/oauth/authorize' }
|
||||
}
|
||||
, { redirect_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/callback.html'
|
||||
, client_id: 'df4d46a358c1f3519c60'
|
||||
}
|
||||
);
|
||||
|
||||
var signinW = window.open(
|
||||
authObj.url
|
||||
, "third-party-provider"
|
||||
);
|
||||
|
||||
var callbackName = '--oauth3-callback-' + authObj.state;
|
||||
|
||||
console.log('authobj: ', authObj);
|
||||
console.log('callback: ',callbackName);
|
||||
|
||||
window[callbackName] = function (obj) {
|
||||
console.log('callback obj: ', obj);
|
||||
$.ajax({
|
||||
url: "https://api.github.com/user"
|
||||
, headers: {authorization: "Bearer " + obj.access_token}
|
||||
}).then( function (ajaxObj) {
|
||||
console.log("Ajax obj: ", ajaxObj);
|
||||
ppid = ajaxObj.id;
|
||||
});
|
||||
};
|
||||
};
|
||||
util.gitlabLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var ppid = '';
|
||||
|
||||
var authObj = window.OAUTH3.core.implicitGrant(
|
||||
{ authorization_dialog: { url:'https://github.com/login/oauth/authorize' }
|
||||
}
|
||||
, { redirect_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/callback.html'
|
||||
, client_id: 'df4d46a358c1f3519c60'
|
||||
}
|
||||
);
|
||||
|
||||
var signinW = window.open(
|
||||
authObj.url
|
||||
, "third-party-provider"
|
||||
);
|
||||
|
||||
var callbackName = '--oauth3-callback-' + authObj.state;
|
||||
|
||||
console.log('authobj: ', authObj);
|
||||
console.log('callback: ',callbackName);
|
||||
|
||||
window[callbackName] = function (obj) {
|
||||
console.log('callback obj: ', obj);
|
||||
$.ajax({
|
||||
url: "https://api.github.com/user"
|
||||
, headers: {authorization: "Bearer " + obj.access_token}
|
||||
}).then( function (ajaxObj) {
|
||||
console.log("Ajax obj: ", ajaxObj);
|
||||
ppid = ajaxObj.id;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
$('body').on('click', '.js-facebook-login', util.facebookLogin);
|
||||
//$('body').on('click', '.js-twitter-login', util.twitterLogin);
|
||||
$('body').on('click', '.js-google-login', util.googleLogin);
|
||||
//$('body').on('click', '.js-github-login', util.githubLogin);
|
||||
//$('body').on('click', '.js-gitlab-login', util.gitlabLogin);
|
||||
//
|
||||
// END 3rd Party Logins
|
||||
//
|
||||
}());
|
|
@ -0,0 +1,57 @@
|
|||
$(function () {
|
||||
'use strict';
|
||||
|
||||
var OAUTH3 = window.OAUTH3;
|
||||
|
||||
//var myPort = window.location.host.replace(/[^:]+(:)?/, '$1');
|
||||
//var providerUri = 'https://localhost.bar.daplie.me' + myPort;
|
||||
var providerUri = 'oauth3.org';
|
||||
|
||||
var auth = OAUTH3.create();
|
||||
|
||||
auth.init().then(function () {
|
||||
$('body').addClass('in');
|
||||
});
|
||||
|
||||
auth.setProvider(providerUri).then(function () {
|
||||
$('.js-signin').removeAttr('disabled');
|
||||
|
||||
return auth.authenticate({ windowType: 'background' }).then(function (session) {
|
||||
console.info("Previously Granted:", session);
|
||||
|
||||
$('.js-signin').removeClass('in').hide();
|
||||
$('.js-logout').show().addClass('in');
|
||||
}, function (err) {
|
||||
console.info("Pre-Auth Fail (okay):", err);
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '.js-signin', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
auth.login().then(function (session) {
|
||||
console.info('authorization tokens!', session);
|
||||
|
||||
$('.js-signin').removeClass('in').hide();
|
||||
$('.js-logout').show().addClass('in');
|
||||
}, function (err) {
|
||||
window.alert(err.message);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('body').on('click', '.js-logout', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
return auth.logout().then(function () {
|
||||
|
||||
localStorage.clear();
|
||||
$('.js-signin').show().addClass('in');
|
||||
$('.js-logout').removeClass('in').hide();
|
||||
});
|
||||
});
|
||||
|
||||
$('.js-logout').hide();
|
||||
});
|
|
@ -0,0 +1,407 @@
|
|||
$(function () {
|
||||
'use strict';
|
||||
|
||||
var OAUTH3 = window.OAUTH3;
|
||||
var CONFIG = {
|
||||
host: OAUTH3.utils.clientUri(window.location)
|
||||
, directives: null // will be populated before the login button appears
|
||||
};
|
||||
var loc = window.location;
|
||||
var util = {};
|
||||
var email;
|
||||
var tpls = {
|
||||
scope: $('.js-scopes-container').html()
|
||||
};
|
||||
$('.js-scopes-container').html('');
|
||||
|
||||
// TODO let query.parse do location.hash || location.search || location
|
||||
var clientParams = OAUTH3.query.parse(window.location.hash || window.location.search);
|
||||
if (/authorization_dialog/.test(window.location.href)) {
|
||||
// OAUTH3.lintClientParams(params, window)
|
||||
// OAUTH3.normalizeClientParams(params, window)
|
||||
if (clientParams.debug) {
|
||||
console.info("'debug' exists, debug mode enabled. :)");
|
||||
}
|
||||
if (-1 === [ 'token', 'code' ].indexOf(clientParams.response_type)) {
|
||||
window.alert("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)");
|
||||
return;
|
||||
}
|
||||
if (!clientParams.state || -1 !== [ 'undefined', 'null' ].indexOf(clientParams.state)) {
|
||||
// TODO check bits
|
||||
window.alert("'state' should exist as a crypto-random string with 128-bits of entropy (32 hex characters)");
|
||||
return;
|
||||
}
|
||||
if (!clientParams.client_id || -1 !== [ 'undefined', 'null' ].indexOf(clientParams.client_id)) {
|
||||
console.warn(
|
||||
"'client_id' should exist as the uri identifying the client,"
|
||||
+ " such as example.com or example.com:8080/my-app or, well,"
|
||||
+ "'" + OAUTH3.url.normalize(window.document.referrer) + "'"
|
||||
);
|
||||
}
|
||||
if (clientParams.client_uri) {
|
||||
console.warn("'client_id' should be used instead of 'client_uri'");
|
||||
}
|
||||
if (!(clientParams.client_id || clientParams.client_uri)) {
|
||||
window.alert("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)");
|
||||
console.error("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)");
|
||||
clientParams.client_id = clientParams.client_uri = OAUTH3.url.normalize(window.document.referrer);
|
||||
}
|
||||
if (!clientParams.redirect_uri) {
|
||||
clientParams.redirect_uri = OAUTH3.url.normalize(clientParams.client_uri)
|
||||
+ "/.well-known/oauth3/callback.html'";
|
||||
window.alert("'redirect_uri' must exist and should point to '" + clientParams.redirect_uri + "'");
|
||||
console.error("'redirect_uri' must exist and should point to '" + clientParams.redirect_uri + "'");
|
||||
}
|
||||
clientParams.referrer = window.document.referrer;
|
||||
}
|
||||
|
||||
function normalizeSession(session) {
|
||||
// TODO casing
|
||||
// TODO expiry calculation
|
||||
// TODO leave this up to OAUTH3
|
||||
session.provider_uri = session.provider_rui || CONFIG.host;
|
||||
session.client_uri = session.client_uri || CONFIG.host; // same as provider in this case
|
||||
}
|
||||
|
||||
function getSession(providerUri) {
|
||||
return OAUTH3.hooks.session.get(providerUri).then(function (session) {
|
||||
if (session && session.access_token) {
|
||||
normalizeSession(session);
|
||||
return OAUTH3.PromiseA.resolve(session);
|
||||
}
|
||||
else {
|
||||
return OAUTH3.PromiseA.reject(new Error("no access_token in session"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getGrants(session) {
|
||||
var clientObj = OAUTH3.query.parse(loc.hash || loc.search);
|
||||
var clientLogo = OAUTH3.url.normalize(clientObj.client_uri) // optional relative logo ?
|
||||
+ '/.well-known/oauth3/logo-128x128.png'
|
||||
;
|
||||
var callbackUrl;
|
||||
// TODO put in directives.json or similar
|
||||
var grantDescriptions = {
|
||||
'oauth3_authn': "Basic secure authentication"
|
||||
, 'wallet': "Access to payments and subscriptions"
|
||||
, 'bucket': "Access to file storage"
|
||||
, 'db': "Access to app data"
|
||||
, 'domains': "Domain registration (and Glue and NS records)" // TODO make an alias
|
||||
, 'domains:glue': "Glue Record management (for vanity nameservers)"
|
||||
, 'domains:ns': "Name Server management"
|
||||
, 'dns': "DNS records (A/AAAA, TXT, SRV, MX, etc)"
|
||||
, '*': "FULL ACCOUNT ACCESS"
|
||||
};
|
||||
|
||||
if ('oauth3_authn' === clientParams.scope) {
|
||||
// implicit ppid grant is automatic
|
||||
console.warn('[security] fix scope checking on backend so that we can do automatic grants');
|
||||
// TODO check user preference if implicit ppid grant is allowed
|
||||
//return generateToken(session, clientObj);
|
||||
}
|
||||
|
||||
$('.js-client-logo').attr('src', clientLogo);
|
||||
//$('.js-user-avatar').attr('src', userAvatar);
|
||||
|
||||
return OAUTH3.authz.scopes(CONFIG.host, session, clientObj).then(function (scopes) {
|
||||
if (!scopes.pending.length) {
|
||||
// looks like we've done all of this before
|
||||
OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientObj, scopes);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is to prevent click-jacking
|
||||
// TODO secure iFrame from click-jacking by requiring input?
|
||||
// ex: input.security-code[type="text"].val(Math.random()); input.js-verify-code[placeholder="Type what you see"]
|
||||
if (OAUTH3._browser.isIframe()) {
|
||||
callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description='
|
||||
+ encodeURIComponent("You're requesting permission in an iframe, but the permissions have not yet been granted")
|
||||
+ '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED');
|
||||
location.href = callbackUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO handle special scopes
|
||||
// ! always show permission dialog
|
||||
// ^ switch user
|
||||
// @n require actual login if not within n seconds
|
||||
// * account takeover
|
||||
scopes.pending.forEach(function (scope) {
|
||||
var $scope = $(tpls.scope);
|
||||
|
||||
$scope.find('.js-scope-toggle').attr('name', scope);
|
||||
$scope.find('.js-scope-toggle').prop('checked', true);
|
||||
if (-1 !== scopes.granted.indexOf(scope)) {
|
||||
$scope.find('.js-scope-toggle').prop('disabled', true);
|
||||
}
|
||||
|
||||
// the front-end recognizes the scope as valid
|
||||
// TODO list scopes in directive
|
||||
if (grantDescriptions[scope]) {
|
||||
$scope.find('.js-scope-desc').text(grantDescriptions[scope]);
|
||||
}
|
||||
else {
|
||||
$scope.find('.js-scope-toggle').prop('checked', false);
|
||||
$scope.find('.js-scope-toggle').prop('disabled', true);
|
||||
$scope.find('.js-scope-desc').text(scope);
|
||||
}
|
||||
|
||||
$('.js-scopes-container').append($scope);
|
||||
});
|
||||
|
||||
$('.js-authz').show().addClass('in');
|
||||
}, function (err) {
|
||||
window.alert('grantResults: ' + err.message);
|
||||
console.error('scope results', err);
|
||||
});
|
||||
}
|
||||
|
||||
util.checkAuthEmail = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var email = $(this).val();
|
||||
|
||||
// wizarding - email detection
|
||||
if (/gmail|yahoo|msn|live/.test(email)) {
|
||||
$('.js-provider-logo').attr('src', 'img/not-provider.png');
|
||||
}
|
||||
else {
|
||||
$('.js-provider-logo').attr('src', 'img/daplie-provider.jpeg');
|
||||
}
|
||||
|
||||
// TODO debounce 150ms
|
||||
// TODO test email by mx record
|
||||
if (/.+@.+\..+/.test(email)) {
|
||||
$('.js-authn-show').removeAttr('disabled');
|
||||
$('.js-oauth3-email').val(email);
|
||||
}
|
||||
else {
|
||||
$('.js-authn-show').prop('disabled', true);
|
||||
}
|
||||
};
|
||||
util.submitAuthEmail = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
$('.js-authn-show').prop('disabled', true);
|
||||
// TODO loading
|
||||
|
||||
email = $('.js-oauth3-email').val();
|
||||
return OAUTH3.authn.loginMeta(CONFIG.directives, {email: email, mock: true}).then(function (userResults) {
|
||||
if (!userResults.data.error) {
|
||||
console.log('User exists:', userResults);
|
||||
}
|
||||
|
||||
if (userResults.data.error) {
|
||||
$('.js-authn-show').removeAttr('disabled');
|
||||
console.warn('User does not exist:', email);
|
||||
console.warn('User Results:', userResults);
|
||||
//window.alert('userResults: ' + userResults.data.error_description || userResults.data.error.message);
|
||||
//return;
|
||||
}
|
||||
|
||||
return OAUTH3.authn.otp(CONFIG.directives, {email: email, mock: true}).then(function (otpResults) {
|
||||
|
||||
if (otpResults.data.error) {
|
||||
window.alert('otpResults: ' + otpResults.data.error_description || otpResults.data.error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var ua = window.navigator.userAgent;
|
||||
$('.js-sniffed-device').text(ua);
|
||||
$('.js-userid-container').removeClass('in').hide();
|
||||
$('.js-authn').show().addClass('in');
|
||||
$('.js-authn-otp-uuid').val(otpResults.data.uuid);
|
||||
|
||||
$('.js-user-email').text(email);
|
||||
});
|
||||
});
|
||||
};
|
||||
util.rememberDevice = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
util.submitLoginCode({
|
||||
rememberDevice: true
|
||||
});
|
||||
};
|
||||
util.rememberDeviceNot = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
util.submitLoginCode({
|
||||
rememberDevice: false
|
||||
});
|
||||
};
|
||||
|
||||
// Reference Implementation
|
||||
|
||||
util.submitLoginCode = function (opts) {
|
||||
|
||||
// TODO
|
||||
// perhaps we should check that the code is valid before continuing to login (so that we don't send the key)
|
||||
|
||||
// TODO
|
||||
// we should be sending the public key for this device as a jwk along with the authentication
|
||||
// (and how long to remember this device)
|
||||
|
||||
var uuid = $('.js-authn-otp-uuid').val();
|
||||
var code = $('.js-authn-otp-code').val().trim();
|
||||
return OAUTH3.authn.resourceOwnerPassword(CONFIG.directives, {
|
||||
// TODO replace with signed hosted file
|
||||
client_agree_tos: 'oauth3.org/tos/draft'
|
||||
, client_id: CONFIG.host
|
||||
, client_uri: CONFIG.host
|
||||
, username: email
|
||||
, password: undefined
|
||||
, otp_code: code
|
||||
// TODO should be otp_id (agnostic of uuid)
|
||||
, otp_uuid: uuid
|
||||
// add expiration to the refresh token and/or public key
|
||||
, expire: opts.rememberDevice || (1 * 60 * 60 * 1000)
|
||||
, mock: true
|
||||
}).then(function (session) {
|
||||
|
||||
$('.js-authn').removeClass('in').hide();
|
||||
|
||||
function getAccount(session) {
|
||||
if (session.token.sub) {
|
||||
return OAUTH3.PromiseA.resolve(session);
|
||||
}
|
||||
|
||||
return OAUTH3.requests.accounts.create(CONFIG.directives, session, {
|
||||
display_name: email.replace(/@.*/, '')
|
||||
, comment: "created for '" + email + "' by '" + CONFIG.host + "'"
|
||||
, priority: 1000 // default priority for first account
|
||||
, name: undefined // TODO we could ask in the UI
|
||||
}).then(function (resp) {
|
||||
var results = resp.data;
|
||||
return OAUTH3.hooks.session.refresh(session, {
|
||||
access_token: (results.access_token || results.accessToken)
|
||||
, refresh_token: (results.refresh_token || results.refreshToken)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return getAccount(session).then(function () {
|
||||
return getGrants(session);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
util.acceptScopesAndLogin = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
// TODO choose from the selected accepted scopes
|
||||
var acceptedScopes = [];
|
||||
|
||||
$('form.js-authorization-decision').find('input[type=checkbox]').each(function (i, el) {
|
||||
var $input = $(el);
|
||||
if ($input.prop('checked')/* && !$input.prop('disabled')*/) {
|
||||
acceptedScopes.push($input.attr('name'));
|
||||
}
|
||||
});
|
||||
|
||||
getSession(CONFIG.host).then(function (session) {
|
||||
var clientParams = OAUTH3.query.parse(loc.hash || loc.search);
|
||||
|
||||
return OAUTH3.authz.scopes(CONFIG.host, session, clientParams).then(function (scopes) {
|
||||
scopes.new = acceptedScopes;
|
||||
return OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes);
|
||||
});
|
||||
}, function (err) {
|
||||
console.error("Accept Scopes and Login");
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
util.closeLoginDeny = function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var loginWinObj = OAUTH3.query.parse(loc.hash || loc.search);
|
||||
|
||||
var denyObj = {
|
||||
error: 'access_denied'
|
||||
, error_description: 'The user has denied access.'
|
||||
, error_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/errors.html#/?error=access_denied'
|
||||
, state: loginWinObj.state
|
||||
, scope: loginWinObj.scope
|
||||
};
|
||||
|
||||
window.location = loginWinObj.redirect_uri + '#' + OAUTH3.query.stringify(denyObj);
|
||||
};
|
||||
util.handleLogout = function () {
|
||||
var clientParams = OAUTH3.query.parse(loc.hash || loc.search);
|
||||
|
||||
localStorage.clear();
|
||||
|
||||
clientParams.redirect_uri += '?' + OAUTH3.query.stringify({
|
||||
state: clientParams.state
|
||||
, debug: clientParams.debug
|
||||
});
|
||||
|
||||
window.location = OAUTH3.url.resolve(clientParams.client_uri, clientParams.redirect_uri);
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Page Setup
|
||||
//
|
||||
$('.js-userid-container').hide();
|
||||
$('.js-authn').hide();
|
||||
$('.js-authz').hide();
|
||||
|
||||
$('body').on('click', '.js-logout', util.handleLogout);
|
||||
$('body').on('click', '.js-authn-show', util.submitAuthEmail);
|
||||
$('body').on('click', '.js-authz-remember-me', util.rememberDevice);
|
||||
$('body').on('click', '.js-authz-remember-me-not', util.rememberDeviceNot);
|
||||
$('body').on('click', '.js-login-allow', util.acceptScopesAndLogin);
|
||||
$('body').on('click', '.js-login-deny', util.closeLoginDeny);
|
||||
$('body').on('keyup', 'form .js-oauth3-email', util.checkAuthEmail);
|
||||
|
||||
function handleAuthorizationDialog() {
|
||||
return getSession(CONFIG.host).then(function (session) {
|
||||
return getGrants(session);
|
||||
}, function (e) {
|
||||
var clientObj = OAUTH3.query.parse(loc.hash || loc.search);
|
||||
// TODO select the providers the client wants to show
|
||||
// providers=daplie.com,facebook.com,google.com // etc
|
||||
// TODO let the client specify switch_user
|
||||
// TODO let the client specify relogin if stale
|
||||
if (OAUTH3._browser.isIframe()) {
|
||||
var callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description='
|
||||
+ encodeURIComponent("You're requesting permission in an iframe, but the user is not yet authenticated")
|
||||
+ '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED');
|
||||
location.href = callbackUrl;
|
||||
}
|
||||
$('.js-userid-container').show();
|
||||
}).then(function () {
|
||||
//$('body').addClass('in');
|
||||
});
|
||||
}
|
||||
|
||||
// Session initialization
|
||||
return $.ajax({ url: '.well-known/oauth3/directives.json' }).then(function (directives) {
|
||||
// TODO cache directives in memory (and storage)
|
||||
CONFIG.directives = directives;
|
||||
directives.issuer = directives.issuer || (window.location.host + window.location.pathname).replace(/\/$/, '');
|
||||
|
||||
$('.js-authorization-dialog').hide();
|
||||
$('.js-logout-container').hide();
|
||||
|
||||
if (/authorization_dialog/.test(window.location.href)) {
|
||||
$('.js-authorization-dialog').show();
|
||||
handleAuthorizationDialog();
|
||||
}
|
||||
else if (/logout/.test(window.location.href)) {
|
||||
$('.js-logout-container').show();
|
||||
}
|
||||
|
||||
$('body').addClass('in');
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
$('body').on('click', '.js-remember-label', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if ($('.js-remember-label').find('.js-remember-checkbox').prop('checked') === true ) {
|
||||
$('.js-remember-label').find('.js-remember-status').removeClass('fa-check-square-o');
|
||||
$('.js-remember-label').find('.js-remember-status').addClass('fa-square-o dap-remember-margin');
|
||||
$('.js-remember-label').find('.js-remember-checkbox').prop('checked', false);
|
||||
$('.js-remember-btn').removeClass('dap-full-button-purple');
|
||||
$('.js-remember-btn').addClass('dap-full-button-green');
|
||||
$('.js-remember-btn').text('SIGN IN ONCE');
|
||||
} else if ($('.js-remember-label').find('.js-remember-checkbox').prop('checked') === false ) {
|
||||
$('.js-remember-label').find('.js-remember-status').removeClass('fa-square-o dap-remember-margin');
|
||||
$('.js-remember-label').find('.js-remember-status').addClass('fa-check-square-o');
|
||||
$('.js-remember-label').find('.js-remember-checkbox').prop('checked', true);
|
||||
$('.js-remember-btn').removeClass('dap-full-button-green');
|
||||
$('.js-remember-btn').addClass('dap-full-button-purple');
|
||||
$('.js-remember-btn').text('SIGN IN FOREVER');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$('body').on('click', '.js-auth-li-enabled', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var $checkbox = $(this)
|
||||
if ($checkbox.find('.js-auth-checkbox').prop('checked') === true ) {
|
||||
$checkbox.removeClass('fa-check-square-o');
|
||||
$checkbox.addClass('fa-square-o');
|
||||
$checkbox.find('.js-auth-checkbox').prop('checked', false);
|
||||
} else if ($checkbox.find('.js-auth-checkbox').prop('checked') === false ) {
|
||||
$checkbox.removeClass('fa-square-o');
|
||||
$checkbox.addClass('fa-check-square-o');
|
||||
$checkbox.find('.js-auth-checkbox').prop('checked', true);
|
||||
}
|
||||
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>loginWhatIs</title>
|
||||
</head>
|
||||
<body>
|
||||
Helpful information about login
|
||||
</body>
|
||||
<script src=""></script>
|
||||
</html>
|
Loading…
Reference in New Issue