Compare commits
43 Commits
pre-issuer
...
master
Author | SHA1 | Date | |
---|---|---|---|
b8253fa500 | |||
|
25d7874104 | ||
|
a2ecd36db4 | ||
|
8c09dccd2e | ||
|
6953f535a1 | ||
|
426d6a4cbe | ||
|
ff5c13f3fc | ||
e4a84ea0b5 | |||
fdf7897b09 | |||
ad454ba7b6 | |||
40bfe2e534 | |||
|
e1701ffdd9 | ||
|
03f5186659 | ||
|
5719f6a78e | ||
|
d28ab68abc | ||
|
8bf164b5aa | ||
|
cc066a0bcd | ||
|
7d18f05baf | ||
|
3c3100a851 | ||
|
3645d66f5c | ||
|
e5cd4ada23 | ||
|
c2b6d2b7ed | ||
|
1b0c5417bf | ||
|
8f30d80b38 | ||
|
3e81aebc4a | ||
|
9b61d7c464 | ||
|
7902dea5f3 | ||
|
cd1ff73eea | ||
|
ea788bcb76 | ||
|
dc5139686e | ||
|
210df2a4c8 | ||
|
22b1d535ca | ||
|
1642251cb7 | ||
|
1d02c1d424 | ||
|
d446057524 | ||
|
624ccf02a0 | ||
|
37bd95fd54 | ||
|
837bdd80c9 | ||
|
c588ea7d3d | ||
|
e9a4ff8f9a | ||
|
e748d8f849 | ||
|
a2364ac874 | ||
|
acb366767a |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
*.*sw*
|
*.*sw*
|
||||||
bower_components/
|
bower_components/
|
||||||
assets/
|
assets/
|
||||||
|
.DS_Store
|
||||||
|
5
CHANGELOG
Normal file
5
CHANGELOG
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
v1.2.1 - Authorization Dialog for ID Issuer
|
||||||
|
* Resource Owner Password token exchange
|
||||||
|
* Public / Private Keypair generation
|
||||||
|
* Public key (remember device) syncing
|
||||||
|
* BUG: Remember me is not operational
|
41
LICENSE
Normal file
41
LICENSE
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Copyright 2017 Daplie, Inc
|
||||||
|
|
||||||
|
This is open source software; you can redistribute it and/or modify it under the
|
||||||
|
terms of either:
|
||||||
|
|
||||||
|
a) the "MIT License"
|
||||||
|
b) the "Apache-2.0 License"
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
Apache-2.0 License Summary
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
30
README.md
30
README.md
@ -1,20 +1,30 @@
|
|||||||
This is a WALNUT module representing the html package for oauth3.org.
|
issuer.html
|
||||||
|
===========
|
||||||
|
|
||||||
It must be installed to `/srv/walnut/packages/pages/issuer@oauth3.org`
|
| [oauth3.js](https://git.oauth3.org/OAuth3/oauth3.js)
|
||||||
|
| *issuer.html*
|
||||||
|
| [issuer.rest.walnut.js](https://git.oauth3.org/OAuth3/issuer.rest.walnut.js)
|
||||||
|
| [issuer.srv](https://git.oauth3.org/OAuth3/issuer.srv)
|
||||||
|
| Sponsored by [ppl](https://ppl.family)
|
||||||
|
|
||||||
|
|
||||||
|
This is a browser application which implements the issuer side of the *authorization_dialog* flow for OAuth3.
|
||||||
|
|
||||||
|
It may be used client-side only (public key or granted scope syncing will be disabled),
|
||||||
|
or will the *issuer.rest.walnut.js* APIs on the backend for full functionality.
|
||||||
|
|
||||||
|
For use with walnut it must be installed to `/opt/walnut/packages/pages/issuer@oauth3.org`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@git.daplie.com:OAuth3/issuer_oauth3.org.git /srv/walnut/packages/pages/issuer@oauth3.org
|
git clone git@git.oauth3.org:OAuth3/org.oauth3.git /opt/walnut/packages/pages/issuer@oauth3.org
|
||||||
ln -s issuer@oauth3.org /srv/walnut/packages/pages/org.oauth3
|
pushd /opt/walnut/packages/pages/issuer@oauth3.org
|
||||||
pushd /srv/walnut/packages/pages/issuer@oauth3.org
|
|
||||||
bash ./install.sh
|
bash ./install.sh
|
||||||
popd
|
popd
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "issuer@oauth3.org" >> /srv/walnut/packages/sites/EXAMPLE.COM
|
echo "issuer@oauth3.org" >> /opt/walnut/var/sites/EXAMPLE.COM
|
||||||
echo "org.oauth3" >> /srv/walnut/packages/sites/EXAMPLE.COM
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This uses the OAuth3 JavaScript SDK `oauth3.js` as a subpackage in `/srv/walnut/packages/pages/issuer@oauth3.org/assets/oauth3.org`.
|
This uses the OAuth3 JavaScript SDK `oauth3.js` as a subpackage in
|
||||||
|
`/opt/walnut/packages/pages/issuer@oauth3.org/assets/oauth3.org`.
|
||||||
The 'login popup' is hosted on our tardigrade proxy VM.
|
|
||||||
|
@ -12,10 +12,6 @@ html, body {
|
|||||||
background-color: #282828;
|
background-color: #282828;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
/*override bootstrap fade*/
|
|
||||||
.fade {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
input.emailInput::placeholder {
|
input.emailInput::placeholder {
|
||||||
font-family : Brown Regular;
|
font-family : Brown Regular;
|
||||||
font-size : 14px;
|
font-size : 14px;
|
||||||
@ -445,3 +441,6 @@ span.dap-small-text.js-scope-desc.noselect {
|
|||||||
color : #808080;
|
color : #808080;
|
||||||
color : rgb(128, 128, 128);
|
color : rgb(128, 128, 128);
|
||||||
}
|
}
|
||||||
|
.error-msg {
|
||||||
|
color: #FDA748;
|
||||||
|
}
|
||||||
|
BIN
img/.DS_Store
vendored
BIN
img/.DS_Store
vendored
Binary file not shown.
66
index.html
66
index.html
@ -11,7 +11,8 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/css/daplie-installer-overrides.css">
|
<link rel="stylesheet" type="text/css" href="/css/daplie-installer-overrides.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="fade mock-main">
|
<body>
|
||||||
|
<div class="fade mock-main">
|
||||||
|
|
||||||
<!-- STEP 1: ask the user where they want to log in -->
|
<!-- STEP 1: ask the user where they want to log in -->
|
||||||
<!-- STEP 2: ask the user for their email -->
|
<!-- STEP 2: ask the user for their email -->
|
||||||
@ -23,8 +24,8 @@
|
|||||||
<!-- Step 5: ask for permissions -->
|
<!-- Step 5: ask for permissions -->
|
||||||
|
|
||||||
<div class="dap-bordered js-userid-container">
|
<div class="dap-bordered js-userid-container">
|
||||||
<p class="org-title">Safelogin.org</p>
|
<p class="org-title">daplie.me</p>
|
||||||
<p class="dap-centered-text dap-normal-text welcome-text center-it">Welcome to a new way to login. Safelogin.org helps you create an Internet ID that allows you to choose what info is shared about you when you login into a site or app online.</p>
|
<p class="dap-centered-text dap-normal-text welcome-text center-it">Welcome to a new way to login. daplie.me helps you create an Internet ID that allows you to choose what info is shared about you when you login into a site or app online.</p>
|
||||||
<form method="post" action="">
|
<form method="post" action="">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="email" class="form-control dap-input js-oauth3-email emailInput" placeholder="Enter an email address to start"></input>
|
<input type="email" class="form-control dap-input js-oauth3-email emailInput" placeholder="Enter an email address to start"></input>
|
||||||
@ -45,7 +46,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dap-bordered js-authn">
|
<div class="dap-bordered js-authn">
|
||||||
<p class="org-title">Safelogin.org</p>
|
<p class="org-title">daplie.me</p>
|
||||||
<!-- <div class="dap-normal-text">
|
<!-- <div class="dap-normal-text">
|
||||||
<span class="fa fa-3x icon-centered-3x fa-purple fa-envelope"></span>
|
<span class="fa fa-3x icon-centered-3x fa-purple fa-envelope"></span>
|
||||||
</div>
|
</div>
|
||||||
@ -61,6 +62,7 @@
|
|||||||
<p class="code-lasts-text">Code lasts for 15 minutes.</p>
|
<p class="code-lasts-text">Code lasts for 15 minutes.</p>
|
||||||
<input type="hidden" class="js-authn-otp-uuid">
|
<input type="hidden" class="js-authn-otp-uuid">
|
||||||
<input class="dap-input js-authn-otp-code form-control" placeholder="XXXX-XXXX-XXXX" maxlength="14"></input>
|
<input class="dap-input js-authn-otp-code form-control" placeholder="XXXX-XXXX-XXXX" maxlength="14"></input>
|
||||||
|
<p class="error-msg"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="dap-centered-div dap-space-on-top form-group">
|
<div class="dap-centered-div dap-space-on-top form-group">
|
||||||
<label class="js-remember-label dap-normal-text">
|
<label class="js-remember-label dap-normal-text">
|
||||||
@ -70,8 +72,7 @@
|
|||||||
<input class="js-remember-checkbox hidden" type="checkbox"></input>
|
<input class="js-remember-checkbox hidden" type="checkbox"></input>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<!-- <button class="dap-full-button-green js-remember-btn js-authz-remember-me">SIGN IN ONCE</button> -->
|
<button type="submit" class="btn btn-primary submit-btn dap-full-button-green js-submit-code-btn" disabled>Submit</button>
|
||||||
<button type="submit" class="btn btn-primary submit-btn dap-full-button-green js-remember-btn js-authz-remember-me">Submit</button>
|
|
||||||
<!-- <a href="./authnocode.html" target="_blank" class="btn btn-primary">Send Code Again</a> -->
|
<!-- <a href="./authnocode.html" target="_blank" class="btn btn-primary">Send Code Again</a> -->
|
||||||
<button class="btn btn-primary js-edit-email-button" type="button">Edit My Email</button>
|
<button class="btn btn-primary js-edit-email-button" type="button">Edit My Email</button>
|
||||||
</form>
|
</form>
|
||||||
@ -85,14 +86,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dap-bordered dap-normal-text js-authz">
|
<div class="dap-bordered dap-normal-text js-authz">
|
||||||
<p class="org-title">Safelogin.org</p>
|
<p class="org-title">daplie.me</p>
|
||||||
<!-- <br> -->
|
<!-- <br> -->
|
||||||
<!-- <div class="dap-user-plus-app">
|
<!-- <div class="dap-user-plus-app">
|
||||||
<span class="fa fa-3x fa-purple fa-user-circle"></span>
|
<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-2x fa-gray fa-plus"></span>
|
||||||
<img class="dap-lab-logo" src="./img/Daplie-Badge-Purple.png" alt="Daplie Labs Logo">
|
<img class="dap-lab-logo" src="./img/Daplie-Badge-Purple.png" alt="Daplie Labs Logo">
|
||||||
</div> -->
|
</div> -->
|
||||||
<p class="dap-centered-text dap-normal-text almost-done-text">Almost done. Now it’s time to set your preferences.</p>
|
<p class="dap-centered-text dap-normal-text almost-done-text">Almost done. Now it's time to set your preferences.</p>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<form class="js-authorization-decision" action="#">
|
<form class="js-authorization-decision" action="#">
|
||||||
@ -139,17 +140,60 @@
|
|||||||
<button type="button" class="dap-full-button-green js-logout btn btn-primary">Sign Out</button>
|
<button type="button" class="dap-full-button-green js-logout btn btn-primary">Sign Out</button>
|
||||||
<img src="./img/sponsored-by.png" class="sponsored-by-logo">
|
<img src="./img/sponsored-by.png" class="sponsored-by-logo">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="fade mock-bare">
|
||||||
|
<div class="container">
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>OAuth3 Playground</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
Login Status:
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
Current Sessions:
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
Approved Devices:
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
Approved Applications:
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!--[if IE]><script src="bower_components/rsvp.js/rsvp.js"></script><![endif]-->
|
<!--[if IE]><script src="bower_components/rsvp.js/rsvp.js"></script><![endif]-->
|
||||||
<script src="./js/jquery-2.2.0.min.js"></script>
|
<script src="./js/jquery-2.2.0.min.js"></script>
|
||||||
<script src="./js/jquery.mask.min.js"></script>
|
<script src="./js/jquery.mask.min.js"></script>
|
||||||
<script src="./js/bootstrap.min.js"></script>
|
<script src="./js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/oauth3.org/oauth3.core.js"></script>
|
||||||
|
<script src="/assets/oauth3.org/oauth3.crypto.js"></script>
|
||||||
|
<script src="/assets/oauth3.org/oauth3.issuer.js"></script>
|
||||||
<script src="./js/issuer.js"></script>
|
<script src="./js/issuer.js"></script>
|
||||||
<script src="./js/script.js"></script>
|
<script src="./js/script.js"></script>
|
||||||
<script src="/assets/oauth3.org/oauth3.core.js"></script>
|
|
||||||
<script src="/assets/oauth3.org/oauth3.issuer.js"></script>
|
|
||||||
<!--script src="/assets/oauth3.org/oauth3.mock.js"></script-->
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -u
|
set -u
|
||||||
# git clone https://git.daplie.com/OAuth3/issuer_oauth3.org.git /srv/walnut/packages/pages/issuer@oauth3.org
|
# git clone https://git.oauth3.org/OAuth3/issuer.html.git /srv/walnut/packages/pages/issuer@oauth3.org
|
||||||
|
# git clone https://git.oauth3.org/OAuth3/azp.html.git /srv/walnut/packages/pages/azp@oauth3.org
|
||||||
|
|
||||||
mkdir -p assets
|
mkdir -p assets
|
||||||
if ! [ -d ./assets/oauth3.org ]; then
|
if ! [ -d ./assets/oauth3.org ]; then
|
||||||
git clone https://git.daplie.com/OAuth3/oauth3.js.git ./assets/oauth3.org
|
git clone https://git.oauth3.org/OAuth3/oauth3.js.git ./assets/oauth3.org
|
||||||
fi
|
fi
|
||||||
pushd ./assets/oauth3.org
|
pushd ./assets/oauth3.org
|
||||||
git checkout v1
|
git checkout v1.2
|
||||||
git pull
|
git pull
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ $(function () {
|
|||||||
var auth = OAUTH3.create();
|
var auth = OAUTH3.create();
|
||||||
|
|
||||||
auth.init().then(function () {
|
auth.init().then(function () {
|
||||||
$('body').addClass('in');
|
$('.mock-main').addClass('in');
|
||||||
});
|
});
|
||||||
|
|
||||||
auth.setProvider(providerUri).then(function () {
|
auth.setProvider(providerUri).then(function () {
|
||||||
|
176
js/issuer.js
176
js/issuer.js
@ -9,7 +9,7 @@ $(function () {
|
|||||||
|
|
||||||
var OAUTH3 = window.OAUTH3;
|
var OAUTH3 = window.OAUTH3;
|
||||||
var CONFIG = {
|
var CONFIG = {
|
||||||
host: OAUTH3.utils.clientUri(window.location)
|
host: OAUTH3.clientUri(window.location)
|
||||||
, directives: null // will be populated before the login button appears
|
, directives: null // will be populated before the login button appears
|
||||||
};
|
};
|
||||||
var loc = window.location;
|
var loc = window.location;
|
||||||
@ -20,22 +20,8 @@ $(function () {
|
|||||||
};
|
};
|
||||||
$('.js-scopes-container').html('');
|
$('.js-scopes-container').html('');
|
||||||
|
|
||||||
/*
|
|
||||||
OAUTH3._hooks.sessions.all = function (providerUri) {
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
OAUTH3._hooks = { sessions: {} };
|
|
||||||
OAUTH3._hooks.sessions.get = function (providerUri, id) {
|
|
||||||
return JSON.parse(window.localStorage.getItem('session-' + providerUri + (id || '')) || 'null');
|
|
||||||
};
|
|
||||||
OAUTH3._hooks.sessions.set = function (providerUri, newSession, id) {
|
|
||||||
window.localStorage.setItem('session-' + providerUri, JSON.stringify(newSession));
|
|
||||||
window.localStorage.setItem('session-' + providerUri + (id || newSession.id || newSession.token.id || ''), JSON.stringify(newSession));
|
|
||||||
return newSession;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO let query.parse do location.hash || location.search || location
|
// TODO let query.parse do location.hash || location.search || location
|
||||||
var clientParams = OAUTH3.query.parse(window.location.hash || window.location.search);
|
var clientParams = OAUTH3.query.parse(loc.hash || loc.search);
|
||||||
if (/authorization_dialog/.test(window.location.href)) {
|
if (/authorization_dialog/.test(window.location.href)) {
|
||||||
// OAUTH3.lintClientParams(params, window)
|
// OAUTH3.lintClientParams(params, window)
|
||||||
// OAUTH3.normalizeClientParams(params, window)
|
// OAUTH3.normalizeClientParams(params, window)
|
||||||
@ -58,12 +44,12 @@ $(function () {
|
|||||||
+ "'" + OAUTH3.url.normalize(window.document.referrer) + "'"
|
+ "'" + OAUTH3.url.normalize(window.document.referrer) + "'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (clientParams.client_uri) {
|
if (clientParams.client_uri && clientParams.client_uri !== clientParams.client_id) {
|
||||||
console.warn("'client_id' should be used instead of 'client_uri'");
|
console.warn("'client_id' should be used instead of 'client_uri'");
|
||||||
}
|
}
|
||||||
if (!(clientParams.client_id || clientParams.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)");
|
window.alert("'client_id' must exist as the uri identifying the client");
|
||||||
console.error("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)");
|
console.error("'client_id' must exist as the uri identifying the client");
|
||||||
clientParams.client_id = clientParams.client_uri = OAUTH3.url.normalize(window.document.referrer);
|
clientParams.client_id = clientParams.client_uri = OAUTH3.url.normalize(window.document.referrer);
|
||||||
}
|
}
|
||||||
if (!clientParams.redirect_uri) {
|
if (!clientParams.redirect_uri) {
|
||||||
@ -99,21 +85,36 @@ $(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getGrants(session) {
|
function getGrants(session) {
|
||||||
var clientObj = OAUTH3.query.parse(loc.hash || loc.search);
|
var clientLogo = OAUTH3.url.normalize(clientParams.client_uri) // optional relative logo ?
|
||||||
var clientLogo = OAUTH3.url.normalize(clientObj.client_uri) // optional relative logo ?
|
|
||||||
+ '/.well-known/oauth3/logo-128x128.png'
|
+ '/.well-known/oauth3/logo-128x128.png'
|
||||||
;
|
;
|
||||||
var callbackUrl;
|
|
||||||
// TODO put in directives.json or similar
|
// TODO put in directives.json or similar
|
||||||
var grantDescriptions = {
|
var grantDescriptions = {
|
||||||
|
// deprecated
|
||||||
'oauth3_authn': "Basic secure authentication"
|
'oauth3_authn': "Basic secure authentication"
|
||||||
|
, 'auth@oauth3.org': "Basic secure authentication"
|
||||||
, 'wallet': "Access to payments and subscriptions"
|
, 'wallet': "Access to payments and subscriptions"
|
||||||
, 'bucket': "Access to file storage"
|
, 'bucket': "Access to file storage"
|
||||||
, 'db': "Access to app data"
|
, 'db': "Access to app data"
|
||||||
, 'domains': "Domain registration (and Glue and NS records)" // TODO make an alias
|
, 'domains': "Domain registration (and Glue and NS records)" // TODO make an alias
|
||||||
|
, 'domains@oauth3.org': "Domain registration (and Glue and NS records)" // TODO make an alias
|
||||||
, 'domains:glue': "Glue Record management (for vanity nameservers)"
|
, 'domains:glue': "Glue Record management (for vanity nameservers)"
|
||||||
, 'domains:ns': "Name Server management"
|
, 'domains:ns': "Name Server management"
|
||||||
, 'dns': "DNS records (A/AAAA, TXT, SRV, MX, etc)"
|
, 'dns': "DNS records (A/AAAA, TXT, SRV, MX, etc)"
|
||||||
|
|
||||||
|
// new
|
||||||
|
, 'hello@example.com': "Hello World Example Access"
|
||||||
|
, 'authn@oauth3.org': "Basic secure authentication"
|
||||||
|
, 'wallet@oauth3.org': "Access to payments and subscriptions"
|
||||||
|
, 'bucket@oauth3.org': "Access to file storage"
|
||||||
|
, 'db@oauth3.org': "Access to app data"
|
||||||
|
, 'domains@oauth3.org': "Domain registration (and Glue and NS records)" // TODO make an alias
|
||||||
|
, 'domains:glue@oauth3.org': "Glue Record management (for vanity nameservers)"
|
||||||
|
, 'domains:ns@oauth3.org': "Name Server management"
|
||||||
|
, 'dns@oauth3.org': "DNS records (A/AAAA, TXT, SRV, MX, etc)"
|
||||||
|
, 'www@daplie.com': "Websites and webapps"
|
||||||
|
|
||||||
, '*': "FULL ACCOUNT ACCESS"
|
, '*': "FULL ACCOUNT ACCESS"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,10 +128,10 @@ $(function () {
|
|||||||
$('.js-client-logo').attr('src', clientLogo);
|
$('.js-client-logo').attr('src', clientLogo);
|
||||||
//$('.js-user-avatar').attr('src', userAvatar);
|
//$('.js-user-avatar').attr('src', userAvatar);
|
||||||
|
|
||||||
return OAUTH3.authz.scopes(CONFIG.host, session, clientObj).then(function (scopes) {
|
return OAUTH3.authz.scopes(CONFIG.host, session, clientParams).then(function (scopes) {
|
||||||
if (!scopes.pending.length) {
|
if (!scopes.pending.length) {
|
||||||
// looks like we've done all of this before
|
// looks like we've done all of this before
|
||||||
OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientObj, scopes);
|
OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,10 +139,12 @@ $(function () {
|
|||||||
// TODO secure iFrame from click-jacking by requiring input?
|
// 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"]
|
// ex: input.security-code[type="text"].val(Math.random()); input.js-verify-code[placeholder="Type what you see"]
|
||||||
if (OAUTH3._browser.isIframe()) {
|
if (OAUTH3._browser.isIframe()) {
|
||||||
callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description='
|
location.href = clientParams.redirect_uri +'#'+ OAUTH3.query.stringify({
|
||||||
+ encodeURIComponent("You're requesting permission in an iframe, but the permissions have not yet been granted")
|
state: clientParams.state
|
||||||
+ '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED');
|
, error: 'access_denied'
|
||||||
location.href = callbackUrl;
|
, 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')
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +168,13 @@ $(function () {
|
|||||||
$scope.find('.js-scope-desc').text(grantDescriptions[scope]);
|
$scope.find('.js-scope-desc').text(grantDescriptions[scope]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$scope.find('.js-scope-toggle').prop('checked', false);
|
//This disables the check/checkbox when we have an unrecognized grant.
|
||||||
$scope.find('.js-scope-toggle').prop('disabled', true);
|
//This is disabled for testing until we can discover grants automatically.
|
||||||
|
//TODO: Enable this when grants are discoverable
|
||||||
|
//TODO: Indicate to user that this is disabled, not just unchecked.
|
||||||
|
//$scope.find('.js-scope-toggle').prop('checked', false);
|
||||||
|
//$scope.find('.check').attr("src", "./img/unpressed-check.png");
|
||||||
|
//$scope.find('.js-scope-toggle').prop('disabled', true);
|
||||||
$scope.find('.js-scope-desc').text(scope);
|
$scope.find('.js-scope-desc').text(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,9 +182,6 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('.js-authz').show().addClass('in');
|
$('.js-authz').show().addClass('in');
|
||||||
}, function (err) {
|
|
||||||
window.alert('grantResults: ' + err.message);
|
|
||||||
console.error('scope results', err);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,19 +217,6 @@ $(function () {
|
|||||||
// TODO loading
|
// TODO loading
|
||||||
|
|
||||||
email = $('.js-oauth3-email').val();
|
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) {
|
return OAUTH3.authn.otp(CONFIG.directives, {email: email, mock: true}).then(function (otpResults) {
|
||||||
|
|
||||||
if (otpResults.data.error) {
|
if (otpResults.data.error) {
|
||||||
@ -240,28 +232,12 @@ $(function () {
|
|||||||
|
|
||||||
$('.js-user-email').text(email);
|
$('.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
|
// Reference Implementation
|
||||||
|
util.submitLoginCode = function (ev) {
|
||||||
util.submitLoginCode = function (opts) {
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// perhaps we should check that the code is valid before continuing to login (so that we don't send the key)
|
// perhaps we should check that the code is valid before continuing to login (so that we don't send the key)
|
||||||
@ -269,7 +245,6 @@ $(function () {
|
|||||||
// TODO
|
// TODO
|
||||||
// we should be sending the public key for this device as a jwk along with the authentication
|
// we should be sending the public key for this device as a jwk along with the authentication
|
||||||
// (and how long to remember this device)
|
// (and how long to remember this device)
|
||||||
|
|
||||||
var uuid = $('.js-authn-otp-uuid').val();
|
var uuid = $('.js-authn-otp-uuid').val();
|
||||||
var code = $('.js-authn-otp-code').val().trim();
|
var code = $('.js-authn-otp-code').val().trim();
|
||||||
return OAUTH3.authn.resourceOwnerPassword(CONFIG.directives, {
|
return OAUTH3.authn.resourceOwnerPassword(CONFIG.directives, {
|
||||||
@ -283,13 +258,10 @@ $(function () {
|
|||||||
// TODO should be otp_id (agnostic of uuid)
|
// TODO should be otp_id (agnostic of uuid)
|
||||||
, otp_uuid: uuid
|
, otp_uuid: uuid
|
||||||
// add expiration to the refresh token and/or public key
|
// add expiration to the refresh token and/or public key
|
||||||
, expire: opts.rememberDevice || (1 * 60 * 60 * 1000)
|
, remember_device: $('.js-remember-label').find('.js-remember-checkbox').prop('checked')
|
||||||
, mock: true
|
, mock: true
|
||||||
}).then(function (session) {
|
}).then(function (session) {
|
||||||
|
|
||||||
$('.js-authn').removeClass('in').hide();
|
$('.js-authn').removeClass('in').hide();
|
||||||
|
|
||||||
function getAccount(session) {
|
|
||||||
if (session.token.sub) {
|
if (session.token.sub) {
|
||||||
return OAUTH3.PromiseA.resolve(session);
|
return OAUTH3.PromiseA.resolve(session);
|
||||||
}
|
}
|
||||||
@ -306,13 +278,15 @@ $(function () {
|
|||||||
, refresh_token: (results.refresh_token || results.refreshToken)
|
, refresh_token: (results.refresh_token || results.refreshToken)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}).then(function (session) {
|
||||||
|
return getGrants(session).catch(function (err) {
|
||||||
return getAccount(session).then(function () {
|
window.alert('grantResults: ' + err.message);
|
||||||
return getGrants(session);
|
console.error('scope results', err);
|
||||||
});
|
});
|
||||||
|
}, function (error) {
|
||||||
|
console.error(error);
|
||||||
|
$('.error-msg').text('Incorrect code');
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
util.acceptScopesAndLogin = function (ev) {
|
util.acceptScopesAndLogin = function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@ -329,8 +303,6 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
getSession(CONFIG.host).then(function (session) {
|
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) {
|
return OAUTH3.authz.scopes(CONFIG.host, session, clientParams).then(function (scopes) {
|
||||||
scopes.new = acceptedScopes;
|
scopes.new = acceptedScopes;
|
||||||
return OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes);
|
return OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes);
|
||||||
@ -344,21 +316,17 @@ $(function () {
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
var loginWinObj = OAUTH3.query.parse(loc.hash || loc.search);
|
|
||||||
|
|
||||||
var denyObj = {
|
var denyObj = {
|
||||||
error: 'access_denied'
|
error: 'access_denied'
|
||||||
, error_description: 'The user has denied access.'
|
, error_description: 'The user has denied access.'
|
||||||
, error_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/errors.html#/?error=access_denied'
|
, error_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/errors.html#/?error=access_denied'
|
||||||
, state: loginWinObj.state
|
, state: clientParams.state
|
||||||
, scope: loginWinObj.scope
|
, scope: clientParams.scope
|
||||||
};
|
};
|
||||||
|
|
||||||
window.location = loginWinObj.redirect_uri + '#' + OAUTH3.query.stringify(denyObj);
|
window.location = clientParams.redirect_uri + '#' + OAUTH3.query.stringify(denyObj);
|
||||||
};
|
};
|
||||||
util.handleLogout = function () {
|
util.handleLogout = function () {
|
||||||
var clientParams = OAUTH3.query.parse(loc.hash || loc.search);
|
|
||||||
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
|
||||||
clientParams.redirect_uri += '?' + OAUTH3.query.stringify({
|
clientParams.redirect_uri += '?' + OAUTH3.query.stringify({
|
||||||
@ -371,21 +339,21 @@ $(function () {
|
|||||||
util.editEmail = function () {
|
util.editEmail = function () {
|
||||||
$('.js-authn').hide();
|
$('.js-authn').hide();
|
||||||
$('.js-userid-container').show();
|
$('.js-userid-container').show();
|
||||||
debugger;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Page Setup
|
// Page Setup
|
||||||
//
|
//
|
||||||
|
$('.js-authorization-dialog').hide();
|
||||||
|
$('.js-logout-container').hide();
|
||||||
$('.js-userid-container').hide();
|
$('.js-userid-container').hide();
|
||||||
$('.js-authn').hide();
|
$('.js-authn').hide();
|
||||||
$('.js-authz').hide();
|
$('.js-authz').hide();
|
||||||
|
|
||||||
$('body').on('click', '.js-logout', util.handleLogout);
|
$('body').on('click', '.js-logout', util.handleLogout);
|
||||||
$('body').on('click', '.js-authn-show', util.submitAuthEmail);
|
$('body').on('click', '.js-authn-show', util.submitAuthEmail);
|
||||||
$('body').on('click', '.js-authz-remember-me', util.rememberDevice);
|
$('body').on('click', '.js-submit-code-btn', util.submitLoginCode);
|
||||||
$('body').on('click', '.js-authz-remember-me-not', util.rememberDeviceNot);
|
|
||||||
$('body').on('click', '.js-login-allow', util.acceptScopesAndLogin);
|
$('body').on('click', '.js-login-allow', util.acceptScopesAndLogin);
|
||||||
$('body').on('click', '.js-login-deny', util.closeLoginDeny);
|
$('body').on('click', '.js-login-deny', util.closeLoginDeny);
|
||||||
$('body').on('click', '.js-edit-email-button', util.editEmail);
|
$('body').on('click', '.js-edit-email-button', util.editEmail);
|
||||||
@ -394,40 +362,33 @@ $(function () {
|
|||||||
function handleAuthorizationDialog() {
|
function handleAuthorizationDialog() {
|
||||||
return getSession(CONFIG.host).then(function (session) {
|
return getSession(CONFIG.host).then(function (session) {
|
||||||
return getGrants(session);
|
return getGrants(session);
|
||||||
}, function (e) {
|
}).catch(function () {
|
||||||
var clientObj = OAUTH3.query.parse(loc.hash || loc.search);
|
|
||||||
// TODO select the providers the client wants to show
|
// TODO select the providers the client wants to show
|
||||||
// providers=daplie.com,facebook.com,google.com // etc
|
// providers=daplie.com,facebook.com,google.com // etc
|
||||||
// TODO let the client specify switch_user
|
// TODO let the client specify switch_user
|
||||||
// TODO let the client specify relogin if stale
|
// TODO let the client specify relogin if stale
|
||||||
if (OAUTH3._browser.isIframe()) {
|
if (OAUTH3._browser.isIframe()) {
|
||||||
var callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description='
|
location.href = clientParams.redirect_uri +'#'+ OAUTH3.query.stringify({
|
||||||
+ encodeURIComponent("You're requesting permission in an iframe, but the user is not yet authenticated")
|
state: clientParams.state
|
||||||
+ '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED');
|
, error: 'access_denied'
|
||||||
location.href = callbackUrl;
|
, 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')
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (clientParams.subject) {
|
if (clientParams.subject) {
|
||||||
$('.js-oauth3-email').val(clientParams.subject);
|
$('.js-oauth3-email').val(clientParams.subject);
|
||||||
$('.js-authn-show').prop('disabled', false);
|
$('.js-authn-show').prop('disabled', false);
|
||||||
}
|
}
|
||||||
$('.js-userid-container').show();
|
$('.js-userid-container').show();
|
||||||
}).then(function () {
|
|
||||||
//$('body').addClass('in');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session initialization
|
// Session initialization
|
||||||
return OAUTH3.discover(
|
return OAUTH3.discover(CONFIG.host, { client_uri: CONFIG.host }).then(function (directives) {
|
||||||
OAUTH3.clientUri(window.location)
|
|
||||||
, { client_uri: OAUTH3.clientUri(window.location) }
|
|
||||||
).then(function (directives) {
|
|
||||||
// TODO cache directives in memory (and storage)
|
// TODO cache directives in memory (and storage)
|
||||||
CONFIG.directives = directives;
|
CONFIG.directives = directives;
|
||||||
directives.issuer = directives.issuer || (window.location.host + window.location.pathname).replace(/\/$/, '');
|
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)) {
|
if (/authorization_dialog/.test(window.location.href)) {
|
||||||
$('.js-authorization-dialog').show();
|
$('.js-authorization-dialog').show();
|
||||||
handleAuthorizationDialog();
|
handleAuthorizationDialog();
|
||||||
@ -436,8 +397,13 @@ $(function () {
|
|||||||
$('.js-logout-container').show();
|
$('.js-logout-container').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('body').addClass('in');
|
if (document.location.hash.slice(1) || document.location.search) {
|
||||||
|
console.log('[DEBUG] search:', document.location.search);
|
||||||
|
console.log('[DEBUG] hash:', document.location.search);
|
||||||
|
$('.mock-main').addClass('in');
|
||||||
|
} else {
|
||||||
|
console.log('[DEBUG] not an auth window');
|
||||||
|
$('.mock-bare').addClass('in');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
75
js/script.js
75
js/script.js
@ -47,50 +47,59 @@ $('body').on('click', '.js-remember-label', function (ev) {
|
|||||||
|
|
||||||
$('body').on('click', '.check', function () {
|
$('body').on('click', '.check', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
var $img = $(this);
|
|
||||||
if($img.attr("src") === "./img/pressed-check.png") {
|
|
||||||
$img.attr("src", "./img/unpressed-check.png");
|
|
||||||
$img.removeClass("is-checked");
|
|
||||||
} else if($img.attr("src") === "./img/unpressed-check.png") {
|
|
||||||
$img.attr("src", "./img/pressed-check.png");
|
|
||||||
$img.addClass("is-checked");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('body').on('click', '.js-auth-li-enabled', function (ev) {
|
$('body').on('click', '.js-auth-li-enabled', function (ev) {
|
||||||
'use strict';
|
'use strict';
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
if ($this.find('.js-auth-checkbox').is(':checked') === true) {
|
var $hiddenCheckbox = $this.find('.js-auth-checkbox');
|
||||||
$this.find('.js-auth-checkbox').prop( "checked", false );
|
var $img = $this.find('.check');
|
||||||
|
var newStatus = $hiddenCheckbox.prop('checked') ? "unchecked" : "checked";
|
||||||
|
|
||||||
|
if(newStatus === 'checked') {
|
||||||
|
|
||||||
|
$img.attr('src', './img/pressed-check.png');
|
||||||
|
$img.addClass("is-checked");
|
||||||
|
$hiddenCheckbox.prop( "checked", true );
|
||||||
} else {
|
} else {
|
||||||
$this.find('.js-auth-checkbox').prop( "checked", true );
|
$img.attr("src", "./img/unpressed-check.png");
|
||||||
|
$img.removeClass("is-checked");
|
||||||
|
$hiddenCheckbox.prop( "checked", false );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// $('body').on('keyup keypress', '.js-authn-otp-code', function (e) {
|
$('body').on('keyup keypress', '.js-authn-otp-code', function (e) {
|
||||||
// 'use strict';
|
'use strict';
|
||||||
// var keyCode = e.keyCode || e.which;
|
// var keyCode = e.keyCode || e.which;
|
||||||
// var regex = new RegExp('^[0-9 \-]+$');
|
// var regex = new RegExp('^[0-9 \-]+$');
|
||||||
// var key = String.fromCharCode(!e.charCode ? e.which : e.charCode);
|
// var key = String.fromCharCode(!e.charCode ? e.which : e.charCode);
|
||||||
// var oauthCode = $(this).val().split('-').join('').replace(/\s/g, '');
|
// var oauthCode = $(this).val().split('-').join('').replace(/\s/g, '');
|
||||||
//
|
//
|
||||||
// if (!regex.test(key)) {
|
// if (!regex.test(key)) {
|
||||||
// event.preventDefault();
|
// event.preventDefault();
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if (oauthCode.length > 0) {
|
// if (oauthCode.length > 0) {
|
||||||
// oauthCode = oauthCode.match(new RegExp('.{1,4}', 'g')).join("-");
|
// oauthCode = oauthCode.match(new RegExp('.{1,4}', 'g')).join("-");
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// $(this).val(oauthCode);
|
// $(this).val(oauthCode);
|
||||||
//
|
//
|
||||||
// if($(this).val().length === $(this).attr("maxlength")){
|
// if($(this).val().length === $(this).attr("maxlength")){
|
||||||
// $('.submit-btn').prop("disabled", false);
|
// $('.submit-btn').prop("disabled", false);
|
||||||
// }
|
// }
|
||||||
// });
|
if ($(this).val().length === 14) {
|
||||||
|
$('.submit-btn').prop('disabled', false);
|
||||||
|
} else {
|
||||||
|
$('.error-msg').empty();
|
||||||
|
$('.submit-btn').prop('disabled', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$('.js-authn-otp-code').mask('####-####-####');
|
$('.js-authn-otp-code').mask('####-####-####');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user