Moved into Gitea
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
BIN
files/FIDO-Conformance-Tools-v1.7.27.1.mp4
Normal file
BIN
files/YubicoResearch.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
files/amiProAbout.jpg
Normal file
|
After Width: | Height: | Size: 908 KiB |
BIN
files/amiProSampleSite01-JP.mp4
Normal file
BIN
files/amipro_sys.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
36
files/amipro_utils.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* amiPro utils
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function setI18NText(i18n_map){
|
||||
for (const key of i18n_map.keys()) {
|
||||
const elm = $("#"+key);
|
||||
if(elm){
|
||||
const lang = window.navigator.language;
|
||||
var elem = i18n_map.get(key)
|
||||
var msg = null
|
||||
if(elem){
|
||||
msg = elem.get(lang)
|
||||
if(!msg)msg=elem.get('en-US');
|
||||
}
|
||||
if(!msg)msg = key+"-"+lang
|
||||
|
||||
$("#"+key).html(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getI18NText(i18n_map, key){
|
||||
const lang = window.navigator.language;
|
||||
var elem = i18n_map.get(key)
|
||||
var msg = null
|
||||
if(elem){
|
||||
msg = elem.get(lang)
|
||||
if(!msg)msg=elem.get('en-US');
|
||||
}
|
||||
if(!msg)msg = key+"-"+lang
|
||||
|
||||
return msg
|
||||
}
|
||||
BIN
files/avatar.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
809
files/bootstrap.js
vendored
Normal file
6511
files/boxicons.css
Normal file
BIN
files/boxicons/boxicons.eot
Normal file
1551
files/boxicons/boxicons.svg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
files/boxicons/boxicons.ttf
Normal file
BIN
files/boxicons/boxicons.woff
Normal file
BIN
files/boxicons/boxicons.woff2
Normal file
BIN
files/build.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
27
files/config.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Config
|
||||
* -------------------------------------------------------------------------------------
|
||||
* ! IMPORTANT: Make sure you clear the browser local storage In order to see the config changes in the template.
|
||||
* ! To clear local storage: (https://www.leadshook.com/help/how-to-clear-local-storage-in-google-chrome-browser/).
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// JS global variables
|
||||
let config = {
|
||||
colors: {
|
||||
primary: '#696cff',
|
||||
secondary: '#8592a3',
|
||||
success: '#71dd37',
|
||||
info: '#03c3ec',
|
||||
warning: '#ffab00',
|
||||
danger: '#ff3e1d',
|
||||
dark: '#233446',
|
||||
black: '#000',
|
||||
white: '#fff',
|
||||
body: '#f4f5fb',
|
||||
headingColor: '#566a7f',
|
||||
axisColor: '#a1acb8',
|
||||
borderColor: '#eceef1'
|
||||
}
|
||||
};
|
||||
16643
files/core.css
Normal file
107
files/demo.css
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* demo.css
|
||||
* File include item demo only specific css only
|
||||
******************************************************************************/
|
||||
|
||||
.menu .app-brand.demo {
|
||||
height: 64px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.app-brand-logo.demo svg {
|
||||
width: 22px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.app-brand-text.demo {
|
||||
font-size: 1.75rem;
|
||||
letter-spacing: -0.5px;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
/* ! For .layout-navbar-fixed added fix padding top tpo .layout-page */
|
||||
/* Detached navbar */
|
||||
.layout-navbar-fixed .layout-wrapper:not(.layout-horizontal):not(.layout-without-menu) .layout-page {
|
||||
padding-top: 76px !important;
|
||||
}
|
||||
/* Default navbar */
|
||||
.layout-navbar-fixed .layout-wrapper:not(.layout-without-menu) .layout-page {
|
||||
padding-top: 64px !important;
|
||||
}
|
||||
|
||||
/* Navbar page z-index issue solution */
|
||||
.content-wrapper .navbar {
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Content
|
||||
******************************************************************************/
|
||||
|
||||
.demo-blocks > * {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.demo-inline-spacing > * {
|
||||
margin: 1rem 0.375rem 0 0 !important;
|
||||
}
|
||||
|
||||
/* ? .demo-vertical-spacing class is used to have vertical margins between elements. To remove margin-top from the first-child, use .demo-only-element class with .demo-vertical-spacing class. For example, we have used this class in forms-input-groups.html file. */
|
||||
.demo-vertical-spacing > * {
|
||||
margin-top: 1rem !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.demo-vertical-spacing.demo-only-element > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.demo-vertical-spacing-lg > * {
|
||||
margin-top: 1.875rem !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.demo-vertical-spacing-lg.demo-only-element > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.demo-vertical-spacing-xl > * {
|
||||
margin-top: 5rem !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.demo-vertical-spacing-xl.demo-only-element > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.rtl-only {
|
||||
display: none !important;
|
||||
text-align: left !important;
|
||||
direction: ltr !important;
|
||||
}
|
||||
|
||||
[dir='rtl'] .rtl-only {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Layout demo
|
||||
******************************************************************************/
|
||||
|
||||
.layout-demo-wrapper {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.layout-demo-placeholder img {
|
||||
width: 900px;
|
||||
}
|
||||
.layout-demo-info {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
616
files/dfido2-lib.js
Normal file
@@ -0,0 +1,616 @@
|
||||
const DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION = 'fido2_user_session'
|
||||
const DFIDO2_LIB_LOCALSTG_NAME_REGISTERED = 'dfido2_lib_registered'
|
||||
const DFIDO2_LIB_LOCALSTG_NAME_SVR_URL = 'dfido2_lib_svr_url'
|
||||
|
||||
/** ===APIs=== */
|
||||
|
||||
if(!localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL)){
|
||||
localStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL, 'https://fido2.amipro.me')
|
||||
}
|
||||
|
||||
function setFidoServerURL(url){
|
||||
localStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL, url);
|
||||
}
|
||||
|
||||
function canTryAutoAuthentication(){
|
||||
//const session_text = localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
//alert('canTryAuth:'+session_text+"|"+(null != localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_REGISTERED)))
|
||||
return null != localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_REGISTERED)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} userId
|
||||
* @param {String} rpId
|
||||
*/
|
||||
async function authenticateFido2(userId = null, rpId = null) {
|
||||
var result
|
||||
result = await doAssertion(userId, rpId);
|
||||
if(result.status === 'ok'){
|
||||
sessionStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION,
|
||||
JSON.stringify({session:result.session, uid:result.username}))
|
||||
localStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_REGISTERED, new Date());
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} userId
|
||||
* @param {String} rpId
|
||||
*/
|
||||
async function registerFido2(userId, userDisplay, rpId = null) {
|
||||
if (isWebAuthnSupported()) {
|
||||
const result = await doAttestation(userId, userDisplay, rpId);
|
||||
if(result.status === 'ok'){
|
||||
localStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_REGISTERED, new Date());
|
||||
sessionStorage.setItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION, JSON.stringify({session:result.session, uid:result.username}))
|
||||
}
|
||||
return result
|
||||
}else return {status:'failed', errorMessage: getI18NErrorMessage('Fido2LibErr101:')}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} rpId
|
||||
* @returns
|
||||
*/
|
||||
async function listUserDevicesFido2(rpId = null) {
|
||||
try {
|
||||
const session_text = sessionStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
if(!session_text) return {status:'ok', devices:[]}
|
||||
|
||||
const session_data = JSON.parse(session_text)
|
||||
|
||||
let req = {session: session_data.session}
|
||||
if (rpId && 0 < rpId.length) {
|
||||
req.rp = { id: rpId };
|
||||
}
|
||||
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/usr/dvs/lst", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(req)
|
||||
});
|
||||
const resp = await response.json();
|
||||
if ('ok' === resp.status && resp.session === session_data.session) {
|
||||
return {status:'ok', devices:resp.devices}
|
||||
} else {
|
||||
return {status:'failed', errorMessage: resp.errorMessage}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
let msg = err.message ? err.message : err;
|
||||
//console.error("Assertion err: ", err);
|
||||
var errRtn = {status:'failed', errorMessage: msg};
|
||||
if(err.name) errRtn.name = err.name
|
||||
return errRtn;
|
||||
}
|
||||
}
|
||||
|
||||
async function delUserDeviceFido2(device_id, rpId = null) {
|
||||
try {
|
||||
const session_text = sessionStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
const session_data = JSON.parse(session_text)
|
||||
|
||||
let req = {session: session_data.session, device_id: device_id}
|
||||
if (rpId && 0 < rpId.length) {
|
||||
req.rp = { id: rpId };
|
||||
}
|
||||
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/usr/dvs/rm", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(req)
|
||||
});
|
||||
const resp = await response.json();
|
||||
|
||||
return resp
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
let msg = err.message ? err.message : err;
|
||||
//console.error("Assertion err: ", err);
|
||||
var errRtn = {status:'failed', errorMessage: msg};
|
||||
if(err.name) errRtn.name = err.name
|
||||
return errRtn;
|
||||
}
|
||||
}
|
||||
|
||||
function getSessionId() {
|
||||
var rtn = null
|
||||
try {
|
||||
const session_text = sessionStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
if(session_text){
|
||||
const session_data = JSON.parse(session_text)
|
||||
|
||||
rtn = session_data.session
|
||||
}
|
||||
|
||||
return rtn
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function validSession(rpId = null) {
|
||||
try {
|
||||
const session_text = sessionStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
if(!session_text) return false
|
||||
|
||||
const session_data = JSON.parse(session_text)
|
||||
|
||||
let req = {session: session_data.session}
|
||||
if (rpId && 0 < rpId.length) {
|
||||
req.rp = { id: rpId };
|
||||
}
|
||||
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/usr/validsession", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(req)
|
||||
});
|
||||
const resp = await response.json();
|
||||
|
||||
return resp.status === 'ok'
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function logoutFido2UserSession(){
|
||||
const session_text = sessionStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION)
|
||||
if(!session_text) return
|
||||
|
||||
const session_data = JSON.parse(session_text)
|
||||
let req = {session: session_data['session'], username: session_data['uid']}
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/usr/delsession", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(req)
|
||||
});
|
||||
|
||||
sessionStorage.removeItem(DFIDO2_LIB_LOCALSTG_NAME_USER_SESSION);
|
||||
}
|
||||
|
||||
async function getRegistrationUser(reg_session_id){
|
||||
try {
|
||||
let req = {session_id: reg_session_id}
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/reg/username", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(req)
|
||||
});
|
||||
const resp = await response.json();
|
||||
|
||||
return resp.username
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function errProcessFido2(result){
|
||||
alert(errMessageFido2(result));
|
||||
}
|
||||
|
||||
function errMessageFido2(result){
|
||||
var rtn
|
||||
if(result.errCode && fido2LibErrCodes.unknown != result.errCode ){
|
||||
switch (result.errCode){
|
||||
case fido2LibErrCodes.user_canceled:
|
||||
rtn=getI18NErrorMessage('Fido2LibErr102:');
|
||||
break;
|
||||
case fido2LibErrCodes.timeout:
|
||||
rtn=getI18NErrorMessage('Fido2LibErr103:');
|
||||
break;
|
||||
default:
|
||||
rtn=result.errorMessage?result.errorMessage:getI18NErrorMessage('Fido2LibErr104:');
|
||||
}
|
||||
}else if(result.name && "InvalidStateError" === result.name){
|
||||
rtn=getI18NErrorMessage('Fido2LibErr105:');
|
||||
}else if(result.errorMessage){
|
||||
const msg = getI18NErrorMessage(result.errorMessage);
|
||||
rtn=msg?msg:result.errorMessage;
|
||||
}else{
|
||||
rtn=getI18NErrorMessage(i18n_messages, 'Fido2LibErr104:');
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
const fido2LibErrCodes = {
|
||||
user_canceled : -101,
|
||||
timeout : -102,
|
||||
unknown : -999
|
||||
}
|
||||
|
||||
const errMsgs = new Map();
|
||||
const fido2LibErrMsgLanguages = {
|
||||
english: 'en-US',
|
||||
japanese: 'ja',
|
||||
chinese_cn: 'zh-CN',
|
||||
//chinese_tw: 'zh-TW',
|
||||
}
|
||||
errMsgs.set(fido2LibErrMsgLanguages.english, new Map());
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr101:', 'Unregistered enterprise authenticator aaguid!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr102:', 'Unable to authenticate with a unique device binding key from another device!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr103:', 'Unable to verify signature!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr104:', 'Key not found!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr105:', 'Username does not exist!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr106:', 'Unique Device ID is null!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr107:', '/attestation/result request body has no ID field!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr108:', 'ID field is not Base64Url encoded in /attestation/result request body!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr109:', '/attestation/result request body has no TYPE field!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr110:', 'TYPE field is not a DOMString in /attestation/result request body!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr111:', 'The TYPE field is not a public key in the /attestation/result request body!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr112:', 'ID field is not a DOMString in /attestation/result request body!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr115:', 'authenticatorData not found!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr116:', 'authenticatorData is not base64 URL encoded!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr117:', 'Signature not found!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr118:', 'Signature is not base64 URL encoded!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr119:', 'No user session!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr120:', 'User has reached the device limit!');
|
||||
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr101:', 'Your browser does not support FIDO2.');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr102:', 'The user canceled.');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr103:', 'The process timeout.');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr104:', 'System error.');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr105:', 'The same authenticator cannot be registered again.');
|
||||
|
||||
errMsgs.set(fido2LibErrMsgLanguages.japanese, new Map());
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr101:', '登録されていないエンタープライズ認証デバイス aaguid!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr102:', '別のデバイスからの一意のデバイス バインド キーで認証できません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr103:', '署名を認証できません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr104:', 'キーが見つかりません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr105:', 'ユーザー名は存在しません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr106:', '固有のデバイス ID が null です!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr107:', '/attestation/result request の本文に ID フィールドがありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr108:', 'ID フィールドは、/attestation/result リクエストの本文でエンコードされた Base64Url ではありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr109:', '/attestation/result リクエストのボディに TYPE フィールドがありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr110:', 'TYPE フィールドは、/attestation/result リクエストの本文の DOMString ではありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr111:', 'TYPE フィールドは、/attestation/result リクエストの本文の公開鍵ではありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr112:', 'ID フィールドは、/attestation/result リクエストの本文の DOMString ではありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr115:', 'authenticatorData が見つかりません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr116:', 'authenticatorData は base64 URL エンコードされていません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr117:', '署名が見つかりません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr118:', '署名は base64 URL エンコードされていません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr119:', 'ユーザーセッションがありません!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr120:', 'ユーザーはデバイスの制限数に達しました!');
|
||||
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr101:', 'お使いのブラウザは FIDO2 をサポートしていません。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr102:', 'ユーザーがキャンセルしました。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr103:', 'プロセスがタイムアウトしました。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr104:', 'システムエラー。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr105:', '同じ認証デバイスを再登録することはできません。');
|
||||
|
||||
errMsgs.set(fido2LibErrMsgLanguages.chinese_cn, new Map());
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr101:', '未注册的企业认证器 aaguid!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr102:', '无法使用来自其他设备的唯一设备绑定密钥进行身份验证!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr103:', '无法验证签名!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr104:', '认证Key未找到!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr105:', '用户名不存在!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr106:', 'Unique Device ID 为 null!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr107:', '/attestation/result请求体没有ID字段!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr108:', 'ID字段不是/attestation/result请求体中编码的Base64Url!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr109:', '/attestation/result请求体没有TYPE字段!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr110:', '/attestation/result 请求正文中的 TYPE 字段不是 DOMString!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr111:', 'TYPE字段不是/attestation/result请求体中的公钥!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr112:', 'ID 字段不是 /attestation/result 请求体中的 DOMString!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr115:', 'authenticatorData 未找到!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr116:', 'authenticatorData 不是 base64 URL 编码!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr117:', '未找到签名!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr118:', '签名不是 base64 URL 编码!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr119:', '未建立用户会话!');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr120:', '用户已达到设备限制数!');
|
||||
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr101:', '您的浏览器不支持FIDO2.');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr102:', '用户取消了操作。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr103:', '操作超时。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr104:', '系统错误。');
|
||||
errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr105:', '无法再次注册相同的认证器。');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} errorMessage
|
||||
* @param {errMsgLanguages} language
|
||||
*/
|
||||
function getI18NErrorMessage(errorMessage, language = null){
|
||||
var lang = language ? language : window.navigator.language
|
||||
var msgs = errMsgs.get(lang)
|
||||
if(!msgs)msgs = errMsgs.get(fido2LibErrMsgLanguages.english)
|
||||
if(errorMessage){
|
||||
const msgHeader = 0<errorMessage.indexOf(':')?errorMessage.substring(0, errorMessage.indexOf(':')):errorMessage
|
||||
const msg = msgs.get(msgHeader+":")
|
||||
return msg?msgHeader+":"+msg:errorMessage;
|
||||
} else return errorMessage;
|
||||
}
|
||||
|
||||
/** ===utils=== */
|
||||
|
||||
function isWebAuthnSupported() {
|
||||
if (window.PublicKeyCredential) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function makePublicKey(attOptsResp) {
|
||||
if (attOptsResp.excludeCredentials) {
|
||||
attOptsResp.excludeCredentials = attOptsResp.excludeCredentials.map(
|
||||
function (cred) {
|
||||
cred.id = _base64ToArrayBuffer(_fromBase64URL(cred.id));
|
||||
cred.transports = ["internal", "usb", "ble", "nfc"];
|
||||
return cred;
|
||||
}
|
||||
);
|
||||
|
||||
//console.log("Attestation Options:");
|
||||
//console.log(attOptsResp);
|
||||
}
|
||||
|
||||
const keys = {
|
||||
publicKey: {
|
||||
attestation: attOptsResp.attestation,
|
||||
authenticatorSelection: attOptsResp.authenticatorSelection,
|
||||
excludeCredentials: attOptsResp.excludeCredentials,
|
||||
rp: attOptsResp.rp,
|
||||
user: {
|
||||
id: _stringToArrayBuffer(attOptsResp.user.id), //_base64ToArrayBuffer(_fromBase64URL(attOptsResp.user.id)),
|
||||
name: attOptsResp.user.name,
|
||||
displayName: attOptsResp.user.displayName,
|
||||
},
|
||||
pubKeyCredParams: attOptsResp.pubKeyCredParams,
|
||||
timeout: attOptsResp.timeout,
|
||||
challenge: _base64ToArrayBuffer(_fromBase64URL(attOptsResp.challenge)),
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
async function doAttestation(username, displayName, rpId, userVerification = 'preferred') {
|
||||
var process_time_limit = Number.MAX_SAFE_INTEGER
|
||||
try {
|
||||
const attestationOptions = {
|
||||
username: username,
|
||||
displayName: encodeURIComponent(displayName),
|
||||
authenticatorSelection: {
|
||||
//authenticatorAttachment: "platform",
|
||||
userVerification: userVerification,
|
||||
requireResidentKey: false,
|
||||
},
|
||||
//attestation: "none",
|
||||
};
|
||||
|
||||
if (rpId && 0 < rpId.length) {
|
||||
attestationOptions.rp = { id: rpId }
|
||||
}
|
||||
|
||||
const svrUrl = localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL)
|
||||
const response = await fetch(svrUrl + "/attestation/options", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(attestationOptions),
|
||||
});
|
||||
|
||||
const resp = await response.json();
|
||||
if (resp.status === "failed") {
|
||||
return {status:'failed', errorMessage: resp.errorMessage}
|
||||
} else {
|
||||
process_time_limit = (new Date()).getTime() + resp.timeout;
|
||||
const res = await navigator.credentials.create(makePublicKey(resp));
|
||||
if (res) {
|
||||
let attResult = {
|
||||
id: res.id,
|
||||
rawId: _toBase64URL(btoa(_bufferToString(res.rawId)))
|
||||
,
|
||||
type: "public-key",
|
||||
response: {
|
||||
clientDataJSON: _toBase64URL(btoa(_bufferToString(res.response.clientDataJSON)))
|
||||
,
|
||||
attestationObject: _toBase64URL(btoa(_bufferToString(res.response.attestationObject)))
|
||||
,
|
||||
},
|
||||
};
|
||||
|
||||
const result = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/attestation/result", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(attResult),
|
||||
});
|
||||
|
||||
const respResult = await result.json();
|
||||
if (respResult) {
|
||||
if (respResult.status === "ok") {
|
||||
return respResult
|
||||
} else {
|
||||
return {status:'failed', errorMessage: respResult.errorMessage}
|
||||
}
|
||||
} else {
|
||||
return {status:'failed', errorMessage: 'Fido2LibErr999:Svr result error'}
|
||||
}
|
||||
} else {
|
||||
return {status:'failed', errorMessage: 'Fido2LibErr999:Undefined Result'};
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
var errRtn = {status:'failed', errorMessage: err.message};
|
||||
if(err.name) errRtn.name = err.name
|
||||
if(err.name && 'NotAllowedError' === err.name){
|
||||
const nowtm = (new Date()).getTime()
|
||||
if(nowtm > process_time_limit){
|
||||
errRtn.errCode = fido2LibErrCodes.timeout
|
||||
}else{
|
||||
errRtn.errCode = fido2LibErrCodes.user_canceled
|
||||
}
|
||||
}else errRtn.errCode = fido2LibErrCodes.unknown
|
||||
|
||||
return errRtn;
|
||||
}
|
||||
}
|
||||
|
||||
async function doAssertion(username = null, rpId = null, userVerification = 'preferred') {
|
||||
var process_time_limit = Number.MAX_SAFE_INTEGER
|
||||
try {
|
||||
let authnOptions;
|
||||
/*if (!username) {
|
||||
authnOptions = {
|
||||
authenticatorSelection: {
|
||||
//authenticatorAttachment: "platform",
|
||||
userVerification: "discouraged"
|
||||
}
|
||||
};
|
||||
} else {
|
||||
authnOptions = {
|
||||
username: username,
|
||||
authenticatorSelection: {
|
||||
//authenticatorAttachment: "platform",
|
||||
userVerification: "preferred"
|
||||
}
|
||||
};
|
||||
}*/
|
||||
authnOptions = {
|
||||
username: username,
|
||||
authenticatorSelection: {
|
||||
//authenticatorAttachment: "platform",
|
||||
userVerification: userVerification
|
||||
}
|
||||
};
|
||||
|
||||
if (rpId && 0 < rpId.length) {
|
||||
authnOptions.rp = { id: rpId };
|
||||
}
|
||||
|
||||
const response = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/assertion/options", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(authnOptions)
|
||||
});
|
||||
const resp = await response.json();
|
||||
if ('ok' === resp.status) {
|
||||
process_time_limit = (new Date()).getTime() + resp.timeout;
|
||||
resp.allowCredentials = resp.allowCredentials || [];
|
||||
let mappedAllowCreds = resp.allowCredentials.map(x => {
|
||||
return {
|
||||
id: _base64ToArrayBuffer(_fromBase64URL(x.id)),
|
||||
type: x.type,
|
||||
transports: x.transports // can set like ['internal', 'usb'] to override server settings
|
||||
};
|
||||
});
|
||||
|
||||
const cred = await navigator.credentials.get({
|
||||
publicKey: {
|
||||
challenge: _base64ToArrayBuffer(_fromBase64URL(resp.challenge)),
|
||||
timeout: resp.timeout,
|
||||
rpId: resp.rpId,
|
||||
userVerification: resp.userVerification,
|
||||
allowCredentials: mappedAllowCreds
|
||||
}
|
||||
});
|
||||
|
||||
if (cred) {
|
||||
let authRequest = {
|
||||
id: cred.id,
|
||||
rawId: Array.from(new Uint8Array(cred.rawId)),
|
||||
type: cred.type,
|
||||
response: {
|
||||
authenticatorData: _toBase64URL(btoa(_bufferToString(cred.response.authenticatorData))),
|
||||
clientDataJSON: _toBase64URL(btoa(_bufferToString(cred.response.clientDataJSON))),
|
||||
signature: _toBase64URL(btoa(_bufferToString(cred.response.signature))),
|
||||
userHandle: _toBase64URL(btoa(_bufferToString(cred.response.userHandle))) //_toBase64URL(btoa(_bufferToString(cred.response.userHandle)))
|
||||
}
|
||||
};
|
||||
const res = await fetch(localStorage.getItem(DFIDO2_LIB_LOCALSTG_NAME_SVR_URL) + "/assertion/result", {
|
||||
method: "POST",
|
||||
cache: "no-cache",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(authRequest)
|
||||
});
|
||||
const result = await res.json();
|
||||
if (result.status === 'ok') {
|
||||
return result
|
||||
} else {
|
||||
return {status:'failed', errorMessage: result.errorMessage}
|
||||
}
|
||||
} else {
|
||||
return {status:'failed', errorMessage: 'Fido2LibErr999:Undefined Result'};
|
||||
}
|
||||
} else {
|
||||
return {status:'failed', errorMessage: resp.errorMessage}
|
||||
}
|
||||
} catch (err) {
|
||||
var errRtn = {status:'failed', errorMessage: err.message};
|
||||
if(err.name) errRtn.name = err.name
|
||||
if(err.name && 'NotAllowedError' === err.name){
|
||||
const nowtm = (new Date()).getTime()
|
||||
if(nowtm > process_time_limit){
|
||||
errRtn.errCode = fido2LibErrCodes.timeout
|
||||
}else{
|
||||
errRtn.errCode = fido2LibErrCodes.user_canceled
|
||||
}
|
||||
}else errRtn.errCode = fido2LibErrCodes.unknown
|
||||
|
||||
return errRtn;
|
||||
}
|
||||
}
|
||||
|
||||
function _toBase64URL(s) {
|
||||
return (s = (s = (s = s.split("=")[0]).replace(/\+/g, "-")).replace(/\//g, "_"));
|
||||
}
|
||||
|
||||
function _base64ToArrayBuffer(base64) {
|
||||
var binary_string = window.atob(base64);
|
||||
var len = binary_string.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function _stringToArrayBuffer(src) {
|
||||
return (new Uint8Array([].map.call(src, function (c) {
|
||||
return c.charCodeAt(0)
|
||||
}))).buffer;
|
||||
}
|
||||
|
||||
function _fromBase64URL(s) {
|
||||
var chk = (s = s.replace(/-/g, "+").replace(/_/g, "/")).length % 4;
|
||||
if (chk) {
|
||||
if (1 === chk) throw new Error("Base64url string is wrong.");
|
||||
s += new Array(5 - chk).join("=");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function _bufferToString(s) {
|
||||
return new Uint8Array(s).reduce((s, e) => s + String.fromCodePoint(e), "");
|
||||
}
|
||||
BIN
files/favicon.ico
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
files/fido-node-fido-conformance-1.7.15.mp4
Normal file
BIN
files/fido.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
files/growup.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
101
files/helpers.js
Normal file
BIN
files/howmuch.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
112
files/jquery.js
vendored
Normal file
118
files/main.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Main
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let menu, animate;
|
||||
|
||||
(function () {
|
||||
// Initialize menu
|
||||
//-----------------
|
||||
|
||||
let layoutMenuEl = document.querySelectorAll('#layout-menu');
|
||||
layoutMenuEl.forEach(function (element) {
|
||||
menu = new Menu(element, {
|
||||
orientation: 'vertical',
|
||||
closeChildren: false
|
||||
});
|
||||
// Change parameter to true if you want scroll animation
|
||||
window.Helpers.scrollToActive((animate = false));
|
||||
window.Helpers.mainMenu = menu;
|
||||
});
|
||||
|
||||
// Initialize menu togglers and bind click on each
|
||||
let menuToggler = document.querySelectorAll('.layout-menu-toggle');
|
||||
menuToggler.forEach(item => {
|
||||
item.addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
window.Helpers.toggleCollapsed();
|
||||
});
|
||||
});
|
||||
|
||||
// Display menu toggle (layout-menu-toggle) on hover with delay
|
||||
let delay = function (elem, callback) {
|
||||
let timeout = null;
|
||||
elem.onmouseenter = function () {
|
||||
// Set timeout to be a timer which will invoke callback after 300ms (not for small screen)
|
||||
if (!Helpers.isSmallScreen()) {
|
||||
timeout = setTimeout(callback, 300);
|
||||
} else {
|
||||
timeout = setTimeout(callback, 0);
|
||||
}
|
||||
};
|
||||
|
||||
elem.onmouseleave = function () {
|
||||
// Clear any timers set to timeout
|
||||
document.querySelector('.layout-menu-toggle').classList.remove('d-block');
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
};
|
||||
if (document.getElementById('layout-menu')) {
|
||||
delay(document.getElementById('layout-menu'), function () {
|
||||
// not for small screen
|
||||
if (!Helpers.isSmallScreen()) {
|
||||
document.querySelector('.layout-menu-toggle').classList.add('d-block');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Display in main menu when menu scrolls
|
||||
let menuInnerContainer = document.getElementsByClassName('menu-inner'),
|
||||
menuInnerShadow = document.getElementsByClassName('menu-inner-shadow')[0];
|
||||
if (menuInnerContainer.length > 0 && menuInnerShadow) {
|
||||
menuInnerContainer[0].addEventListener('ps-scroll-y', function () {
|
||||
if (this.querySelector('.ps__thumb-y').offsetTop) {
|
||||
menuInnerShadow.style.display = 'block';
|
||||
} else {
|
||||
menuInnerShadow.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Init helpers & misc
|
||||
// --------------------
|
||||
|
||||
// Init BS Tooltip
|
||||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// Accordion active class
|
||||
const accordionActiveFunction = function (e) {
|
||||
if (e.type == 'show.bs.collapse' || e.type == 'show.bs.collapse') {
|
||||
e.target.closest('.accordion-item').classList.add('active');
|
||||
} else {
|
||||
e.target.closest('.accordion-item').classList.remove('active');
|
||||
}
|
||||
};
|
||||
|
||||
const accordionTriggerList = [].slice.call(document.querySelectorAll('.accordion'));
|
||||
const accordionList = accordionTriggerList.map(function (accordionTriggerEl) {
|
||||
accordionTriggerEl.addEventListener('show.bs.collapse', accordionActiveFunction);
|
||||
accordionTriggerEl.addEventListener('hide.bs.collapse', accordionActiveFunction);
|
||||
});
|
||||
|
||||
// Auto update layout based on screen size
|
||||
window.Helpers.setAutoUpdate(true);
|
||||
|
||||
// Toggle Password Visibility
|
||||
window.Helpers.initPasswordToggle();
|
||||
|
||||
// Speech To Text
|
||||
window.Helpers.initSpeechToText();
|
||||
|
||||
// Manage menu expanded/collapsed with templateCustomizer & local storage
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// If current layout is horizontal OR current window screen is small (overlay menu) than return from here
|
||||
if (window.Helpers.isSmallScreen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If current layout is vertical and current window screen is > small
|
||||
|
||||
// Auto update menu collapsed/expanded based on the themeConfig
|
||||
window.Helpers.setCollapsed(true, false);
|
||||
})();
|
||||
101
files/menu.js
Normal file
BIN
files/opensrc.jpg
Normal file
|
After Width: | Height: | Size: 133 KiB |
68
files/page-auth.css
Normal file
BIN
files/passkeys.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
211
files/perfect-scrollbar.css
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Container style
|
||||
*/
|
||||
.ps {
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scrollbar rail styles
|
||||
*/
|
||||
.ps__rail-x {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: background-color 0.2s linear, opacity 0.2s linear;
|
||||
-webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
|
||||
height: 15px;
|
||||
/* there must be 'bottom' or 'top' for ps__rail-x */
|
||||
bottom: 0px;
|
||||
/* please don't change 'position' */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ps__rail-y {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: background-color 0.2s linear, opacity 0.2s linear;
|
||||
-webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
|
||||
width: 15px;
|
||||
/* there must be 'right' or 'left' for ps__rail-y */
|
||||
right: 0;
|
||||
/* please don't change 'position' */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ps--active-x > .ps__rail-x,
|
||||
.ps--active-y > .ps__rail-y {
|
||||
display: block;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ps:hover > .ps__rail-x,
|
||||
.ps:hover > .ps__rail-y,
|
||||
.ps--focus > .ps__rail-x,
|
||||
.ps--focus > .ps__rail-y,
|
||||
.ps--scrolling-x > .ps__rail-x,
|
||||
.ps--scrolling-y > .ps__rail-y {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.ps .ps__rail-x:hover,
|
||||
.ps .ps__rail-y:hover,
|
||||
.ps .ps__rail-x:focus,
|
||||
.ps .ps__rail-y:focus,
|
||||
.ps .ps__rail-x.ps--clicking,
|
||||
.ps .ps__rail-y.ps--clicking {
|
||||
background-color: #eee;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scrollbar thumb styles
|
||||
*/
|
||||
.ps__thumb-x {
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s linear, height 0.2s ease-in-out;
|
||||
-webkit-transition: background-color 0.2s linear, height 0.2s ease-in-out;
|
||||
height: 6px;
|
||||
/* there must be 'bottom' for ps__thumb-x */
|
||||
bottom: 2px;
|
||||
/* please don't change 'position' */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ps__thumb-y {
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s linear, width 0.2s ease-in-out;
|
||||
-webkit-transition: background-color 0.2s linear, width 0.2s ease-in-out;
|
||||
width: 6px;
|
||||
/* there must be 'right' for ps__thumb-y */
|
||||
right: 2px;
|
||||
/* please don't change 'position' */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ps__rail-x:hover > .ps__thumb-x,
|
||||
.ps__rail-x:focus > .ps__thumb-x,
|
||||
.ps__rail-x.ps--clicking .ps__thumb-x {
|
||||
background-color: #999;
|
||||
height: 11px;
|
||||
}
|
||||
|
||||
.ps__rail-y:hover > .ps__thumb-y,
|
||||
.ps__rail-y:focus > .ps__thumb-y,
|
||||
.ps__rail-y.ps--clicking .ps__thumb-y {
|
||||
background-color: #999;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
/* MS supports */
|
||||
@supports (-ms-overflow-style: none) {
|
||||
.ps {
|
||||
overflow: auto !important;
|
||||
}
|
||||
}
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
.ps {
|
||||
overflow: auto !important;
|
||||
}
|
||||
}
|
||||
.ps {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ps__rail-x {
|
||||
height: 0.25rem;
|
||||
}
|
||||
|
||||
.ps__rail-y {
|
||||
width: 0.25rem;
|
||||
}
|
||||
|
||||
.ps__rail-x,
|
||||
.ps__rail-y,
|
||||
.ps__thumb-x,
|
||||
.ps__thumb-y {
|
||||
border-radius: 10rem;
|
||||
}
|
||||
|
||||
.ps__rail-x:hover,
|
||||
.ps__rail-x:focus,
|
||||
.ps__rail-x.ps--clicking,
|
||||
.ps__rail-x:hover > .ps__thumb-x,
|
||||
.ps__rail-x:focus > .ps__thumb-x,
|
||||
.ps__rail-x.ps--clicking > .ps__thumb-x {
|
||||
height: 0.375rem;
|
||||
}
|
||||
|
||||
.ps__rail-y:hover,
|
||||
.ps__rail-y:focus,
|
||||
.ps__rail-y.ps--clicking,
|
||||
.ps__rail-y:hover > .ps__thumb-y,
|
||||
.ps__rail-y:focus > .ps__thumb-y,
|
||||
.ps__rail-y.ps--clicking > .ps__thumb-y {
|
||||
width: 0.375rem;
|
||||
}
|
||||
|
||||
.ps__thumb-x {
|
||||
height: 0.25rem;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ps__thumb-y {
|
||||
width: 0.25rem;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.light-style .ps__thumb-x,
|
||||
.light-style .ps__thumb-y {
|
||||
background-color: rgba(67, 89, 113, 0.4);
|
||||
}
|
||||
.light-style .ps__rail-x:hover,
|
||||
.light-style .ps__rail-y:hover,
|
||||
.light-style .ps__rail-x:focus,
|
||||
.light-style .ps__rail-y:focus,
|
||||
.light-style .ps__rail-x.ps--clicking,
|
||||
.light-style .ps__rail-y.ps--clicking {
|
||||
background-color: rgba(67, 89, 113, 0.2);
|
||||
}
|
||||
.light-style .ps__rail-x:hover > .ps__thumb-x,
|
||||
.light-style .ps__rail-y:hover > .ps__thumb-y,
|
||||
.light-style .ps__rail-x:focus > .ps__thumb-x,
|
||||
.light-style .ps__rail-y:focus > .ps__thumb-y,
|
||||
.light-style .ps__rail-x.ps--clicking > .ps__thumb-x,
|
||||
.light-style .ps__rail-y.ps--clicking > .ps__thumb-y {
|
||||
background-color: rgba(67, 89, 113, 0.7);
|
||||
}
|
||||
.light-style .ps-inverted .ps__rail-x:hover,
|
||||
.light-style .ps-inverted .ps__rail-y:hover,
|
||||
.light-style .ps-inverted .ps__rail-x:focus,
|
||||
.light-style .ps-inverted .ps__rail-y:focus,
|
||||
.light-style .ps-inverted .ps__rail-x.ps--clicking,
|
||||
.light-style .ps-inverted .ps__rail-y.ps--clicking {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.light-style .ps-inverted .ps__thumb-x,
|
||||
.light-style .ps-inverted .ps__thumb-y {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
.light-style .ps-inverted .ps__rail-x:hover > .ps__thumb-x,
|
||||
.light-style .ps-inverted .ps__rail-y:hover > .ps__thumb-y,
|
||||
.light-style .ps-inverted .ps__rail-x:focus > .ps__thumb-x,
|
||||
.light-style .ps-inverted .ps__rail-y:focus > .ps__thumb-y,
|
||||
.light-style .ps-inverted .ps__rail-x.ps--clicking > .ps__thumb-x,
|
||||
.light-style .ps-inverted .ps__rail-y.ps--clicking > .ps__thumb-y {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@supports (-moz-appearance: none) {
|
||||
#both-scrollbars-example {
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
112
files/perfect-scrollbar.js
Normal file
112
files/popper.js
Normal file
BIN
files/portal_conf_jp.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
files/portal_reg_jp.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
806
files/theme-default.css
Normal file
BIN
files/toshiba_project.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
1212
files/ua-parser.js
Normal file
421
index.html
Normal file
@@ -0,0 +1,421 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html
|
||||
lang="en-US"
|
||||
class="light-style"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-850DCHX9EJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-850DCHX9EJ');
|
||||
</script>
|
||||
|
||||
<title> Home - amiPro </title>
|
||||
|
||||
<meta name="description" content="最も簡単に統合できるパスキー・クラウド・サービス; the easiest to integrate Passkey cloud service; Cloud services of FIDO2 and WebAuthN" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="files/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Icons. Uncomment required icon fonts -->
|
||||
<link rel="stylesheet" href="files/boxicons.css?v=20230405" />
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="files/core.css" class="template-customizer-core-css" />
|
||||
<link rel="stylesheet" href="files/theme-default.css" class="template-customizer-theme-css" />
|
||||
<link rel="stylesheet" href="files/demo.css" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet" href="files/perfect-scrollbar.css" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="files/helpers.js"></script>
|
||||
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
<script src="files/config.js"></script>
|
||||
|
||||
<script src="files/jquery.js"></script>
|
||||
<script src="files/popper.js"></script>
|
||||
<script src="files/bootstrap.js"></script>
|
||||
<script src="files/perfect-scrollbar.js"></script>
|
||||
<script src="files/menu.js"></script>
|
||||
<script src="files/main.js"></script>
|
||||
|
||||
<script src="files/ua-parser.js"></script>
|
||||
|
||||
<script src="files/amipro_utils.js?v=20230401402"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var user_id, reg_session_id;
|
||||
|
||||
const i18n_messages = new Map();
|
||||
|
||||
var lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro - The easiest to integrate and manage Passkey cloud service");
|
||||
lang_map.set("zh-CN", "amiPro - 最易集成、易管理的 Passkey 云服务");
|
||||
lang_map.set("ja", "amiPro - 最も簡単に統合・管理できるパスキー・クラウド・サービス");
|
||||
i18n_messages.set("label_welcome", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Management Portal");
|
||||
lang_map.set("zh-CN", "管理门户");
|
||||
lang_map.set("ja", "管理ポータル");
|
||||
i18n_messages.set("label_portal", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Contact us (sales@amipro.me)");
|
||||
lang_map.set("zh-CN", "联系我们(sales@amipro.me)");
|
||||
lang_map.set("ja", "お問い合わせ(sales@amipro.me)");
|
||||
i18n_messages.set("title_contact", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "What is Passkey");
|
||||
lang_map.set("zh-CN", "什么是Passkey");
|
||||
lang_map.set("ja", "パスキー(Passkey)とは");
|
||||
i18n_messages.set("title_what_passkey", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkeys replace passwords and provide faster, more accessible, and more secure website sign‑ins. Unlike passwords, passkeys are phishing‑resistant and more reliable. With support from major companies including Apple, Google, and NTT, 2023 marked the beginning of passkeys entering the consumer market.");
|
||||
lang_map.set("zh-CN", "Passkey 取代密码,提供更快、更易用且更安全的网站登录。与密码不同,Passkey 稳定可靠并且可抵御网络钓鱼。在包括苹果、谷歌、NTT 等大型公司的支持下,2023 年成为 Passkey 进入消费者市场的元年。");
|
||||
lang_map.set("ja", "パスキーはパスワードを置き換え、より高速で、よりアクセスしやすく<br>より安全なウェブサイトのサインインを提供します。パスワードとは異なり、<br>常に堅牢でフィッシングに耐性があります。<br>Apple、Google、NTTなどの大手企業のサポートを受けて、<br>2023年はPasskeyを一般消費者市場に導入する年です。");
|
||||
i18n_messages.set("info_what_passkey", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey benefits");
|
||||
lang_map.set("zh-CN", "Passkey的优势");
|
||||
lang_map.set("ja", "パスキーのメリット");
|
||||
i18n_messages.set("title_passkey_merits", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkeys not only provide a more secure login method; they can also increase your website’s business value:<br>1. Faster sign‑in can <b>improve</b> conversion rates<br>2. No password resets can <b>reduce</b> support costs");
|
||||
lang_map.set("zh-CN", "Passkey 不仅提供更安全的登录方式,也能提升您网站的商业价值:<br>1、更快速的登录可<b>提高</b>转化率<br>2、无需找回密码可<b>降低</b>客服成本");
|
||||
lang_map.set("ja", "パスキーは安全なログイン方法を提供するだけでなく、<br>Webサイトのビジネス価値の向上にもつながります。<br>1. より高速なログインはコンバージョン率の<b>向上</b>に寄与<br>2. パスワード再設定が不要なためサポートコストの<b>削減</b>につながります。");
|
||||
i18n_messages.set("info_passkey_merits", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Merits");
|
||||
lang_map.set("zh-CN", "优势");
|
||||
lang_map.set("ja", "メリット");
|
||||
i18n_messages.set("label_merits", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Why amiPro: Standards compliance");
|
||||
lang_map.set("zh-CN", "amiPro 的优势:标准合规");
|
||||
lang_map.set("ja", "amiProの強み:規格準拠");
|
||||
i18n_messages.set("title_amipro_fido", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro is designed based on the FIDO standard and has passed the FIDO2 conformance test 100%.<br>From the browser to the SDK, everything aligns with the latest FIDO2 standard, making it safer and easier to maintain.<br>Meanwhile, amiPro provides extended features to enhance security and integration convenience.");
|
||||
lang_map.set("zh-CN", "amiPro基于FIDO标准设计,100%通过FIDO2兼容测试。<br>从浏览器到SDK全部统一至FIDO2最新标准,更安全更易维护。<br>同时提供扩展功能,增强安全性及集成便利性");
|
||||
lang_map.set("ja", "amiProはFIDO規格に基づいて設計され、FIDO2互換性テストを100%パスしています<br>ブラウザから SDK に至るまで、すべてが最新の FIDO2 標準に統一されており、より安全で保守が容易です。<br>同時に、amiProはセキュリティと統合の互換性を高めるための拡張機能を提供します。");
|
||||
i18n_messages.set("info_amipro_fido", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "FIDO conformance test");
|
||||
lang_map.set("zh-CN", "FIDO兼容性测试");
|
||||
lang_map.set("ja", "FIDO準拠性テスト");
|
||||
i18n_messages.set("label_fido_video", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Why amiPro: Open source");
|
||||
lang_map.set("zh-CN", "amiPro的优势:开源");
|
||||
lang_map.set("ja", "amiProの強み:オープンソース");
|
||||
i18n_messages.set("title_open_src", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro's core is completely open source, thus providing complete verifiability and security.<br>Not only the FIDO2 server, but also the iOS/Android SDK for App development are completely open source.");
|
||||
lang_map.set("zh-CN", "amiPro的核心完全永久开源,从而提供完全的可验证性和安全性。<br>不仅FIDO2服务器,App开发用iOS/Android SDK也完全开源。");
|
||||
lang_map.set("ja", "amiPro のコアは完全にオープンソースであり、完全な検証性とセキュリティを提供します。<br>FIDO2 サーバーだけでなく、アプリ開発用の iOS / Android SDK も完全にオープンソースです。");
|
||||
i18n_messages.set("info_open_src", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Open source project");
|
||||
lang_map.set("zh-CN", "开源项目");
|
||||
lang_map.set("ja", "オープンソースプロジェクト");
|
||||
i18n_messages.set("label_open_src", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "How to integrate");
|
||||
lang_map.set("zh-CN", "集成方法");
|
||||
lang_map.set("ja", "導入方法");
|
||||
i18n_messages.set("title_howto", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro provides standards‑based interfaces and an easy‑to‑use JavaScript SDK for integration. From device registration and sign‑in to device reset management, everything can be implemented easily.<br>No need to modify your server backend—use front‑end JavaScript to integrate.<br>We also provide iOS/Android SDKs for app development.<br>Providing integration support (sales@amipro.me)");
|
||||
lang_map.set("zh-CN", "amiPro 提供基于标准的接口以及便于集成的 JavaScript SDK。从设备注册、登录到设备重置管理,都可以轻松实现。<br>无需修改您的服务器后端,仅使用前端 JavaScript 即可完成集成。<br>同时提供用于 App 开发的 iOS/Android SDK,便于集成。<br>提供导入支持(sales@amipro.me)");
|
||||
lang_map.set("ja", "amiProは、統合のための標準的なインターフェイスと便利なJavaScript SDKを提供します。<br>デバイスの登録、ログインからデバイスのリセット管理まで、すべて簡単に実装できます。<br>サーバーのバックグラウンドを変更する必要はありません、<br>フロントエンド JavaScript を使用するだけで統合を実現できます。<br>同時に、App 開発用の iOS / Android SDK も提供しています。 導入サポートが必要な場合は<br> sales@amipro.me へメールでご連絡ください。");
|
||||
i18n_messages.set("info_howto", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Integration Steps");
|
||||
lang_map.set("zh-CN", "集成步骤");
|
||||
lang_map.set("ja", "導入手順");
|
||||
i18n_messages.set("label_integration", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Cost");
|
||||
lang_map.set("zh-CN", "费用");
|
||||
lang_map.set("ja", "費用");
|
||||
i18n_messages.set("title_howmuch", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro provides the highest cost performance billing model based on the number of <b>active users</b>. Regardless of the number of registered users, you only need to pay for per active user (users who log in at least once a month) per month or per authentication.<br>Provide discount plans for sites with a large number of active users.");
|
||||
lang_map.set("zh-CN", "提供基于<b>活动用户数</b>的最高性价比的计费模式。与注册用户数无关,每月只需为每个活动用户(每月至少登录一次的用户)或者按认证次数支付费用。<br>对活动用户数较大的网站提供优惠方案。");
|
||||
lang_map.set("ja", "<b>アクティブユーザー数</b>に基づいた最高のコストパフォーマンスの課金モデルを提供します。<br>登録ユーザー数に関係なく、毎月アクティブユーザー(毎月最低1回ログインするユーザー)或いは認証利用数ごとのお支払いとなります。<br>割引プランもご用意しております。");
|
||||
i18n_messages.set("info_howmuch", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "One month free trial<br>(After free registration of the management portal, all functions are free to try for one month)");
|
||||
lang_map.set("zh-CN", "一个月免费试用<br>(免费注册管理门户后,所有功能免费试用一个月)");
|
||||
lang_map.set("ja", "1ヶ月間の無料トライアル<br>(管理ポータルの無料登録後、すべての機能を1ヶ月間無料でお試しいただけます)");
|
||||
i18n_messages.set("btn_portal", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro LLC.");
|
||||
lang_map.set("zh-CN", "amiPro LLC.");
|
||||
lang_map.set("ja", "amiPro合同会社");
|
||||
i18n_messages.set("company_name", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Established March 3, 2023");
|
||||
lang_map.set("zh-CN", "2023年3月3日成立");
|
||||
lang_map.set("ja", "2023年3月3日設立");
|
||||
i18n_messages.set("company_open", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "2F Kuwano Building, 6-23-4 Jingumae, Shibuya-ku, Tokyo 150-0001");
|
||||
lang_map.set("zh-CN", "东京都涩谷区神宫前6-23-4桑野大厦2F 邮编 150-0001");
|
||||
lang_map.set("ja", "〒150-0001 東京都渋谷区神宮前六丁目23番4号 桑野ビル2階");
|
||||
i18n_messages.set("company_addr", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "More details");
|
||||
lang_map.set("zh-CN", "更多详情");
|
||||
lang_map.set("ja", "詳細");
|
||||
i18n_messages.set("label_open_passkey", lang_map);
|
||||
|
||||
/*lang_map = new Map();
|
||||
lang_map.set("en-US", "* Latest company profile <a href='files/amiProAbout.jpg' target=' _blank'>Flyer</a>");
|
||||
lang_map.set("zh-CN", "* 最新公司简介<a href='files/amiProAbout.jpg' target='_blank'>传单</a>");
|
||||
lang_map.set("ja", "* 最新会社概要<a href='files/amiProAbout.jpg' target='_blank'>チラシ</a>");*/
|
||||
i18n_messages.set("top_msg", lang_map);
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "FIDO2: From $18.82 billion in 2024 to $60.34 billion in 2032");
|
||||
lang_map.set("zh-CN", "FIDO2:从 2024 年的 188.2 亿美元增至 2032 年的 603.4 亿美元");
|
||||
lang_map.set("ja", "FIDO2: 2024年の188.2億米ドルから2032年には603.4億米ドルへ");
|
||||
i18n_messages.set("top_msg", lang_map);
|
||||
|
||||
|
||||
window.onload = async function() {
|
||||
setI18NText(i18n_messages)
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout wrapper -->
|
||||
<div class="layout-wrapper layout-content-navbar">
|
||||
<div class="layout-container">
|
||||
<!-- Layout container -->
|
||||
<div class="layout-page">
|
||||
<!-- Navbar -->
|
||||
|
||||
<nav
|
||||
class="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
|
||||
id="layout-navbar"
|
||||
>
|
||||
|
||||
|
||||
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
|
||||
<div class="navbar-nav align-items-center">
|
||||
<div class="nav-item d-flex align-items-center">
|
||||
<img src="files/favicon.ico" alt="amiPro" width="80%">
|
||||
<span id="label_welcome" style="padding-left: 60px;white-space: nowrap; font-size: x-large; color: #000000;" class="d-none d-lg-block"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://portal.amipro.me" target="_blank" style="width: 100%; text-align: right;">
|
||||
<i class="bx bx-link bx-sm"></i>
|
||||
<span id="label_portal"> Portal</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- / Navbar -->
|
||||
|
||||
<!-- Dynamic horizontal scrolling prompt information -->
|
||||
<div class="card shadow-none bg-transparent border border-danger" style="text-align: center; margin: 1rem 2rem;">
|
||||
<h5 class="card-title" id="top_msg" style="margin-top: 0.8rem;">Top messgaes</h5>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Content wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content -->
|
||||
|
||||
<div class="row row-cols-1 row-cols-md-3 g-4 mb-5" style="margin: 12px;">
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/passkeys.jpg" alt="Passkeys">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_what_passkey">What's Passkey</h5>
|
||||
<p class="card-text" id="info_what_passkey">
|
||||
What is Passkey
|
||||
</p><br>
|
||||
<a href="passkey.html" target="_blank" class="btn btn-primary" id="label_open_passkey" style="position: absolute;bottom: 10px;">About Passkey</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/growup.jpg" alt="Growup">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_passkey_merits">Passkey's merits</h5>
|
||||
<p class="card-text" id="info_passkey_merits">
|
||||
Passkey's merits
|
||||
</p><br>
|
||||
<a href="merits.html" target="_blank" class="btn btn-primary" id="label_merits" style="position: absolute;bottom: 10px;">Merits</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/fido.jpg" alt="amiPro Strength: fido">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_amipro_fido">amiPro FIDO</h5>
|
||||
<p class="card-text" id="info_amipro_fido">
|
||||
amiPro FIDO
|
||||
</p><br>
|
||||
<a href="files/FIDO-Conformance-Tools-v1.7.27.1.mp4" target="_blank" class="btn btn-primary" id="label_fido_video" style="position: absolute;bottom: 10px;">FIDO Video</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/opensrc.jpg" alt="Open source">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_open_src">Open src</h5>
|
||||
<p class="card-text" id="info_open_src">
|
||||
Open src
|
||||
</p><br>
|
||||
<a href="https://github.com/dqj1998/fido2-node" target="_blank" class="btn btn-primary" id="label_open_src" style="position: absolute;bottom: 10px;">Open src</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/build.jpg" alt="how to">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_howto">How to</h5>
|
||||
<p class="card-text" id="info_howto">
|
||||
How to
|
||||
</p><br>
|
||||
<a href="integration.html" target="_blank" class="btn btn-primary" id="label_integration" style="position: absolute;bottom: 10px;">integration</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="files/howmuch.jpg" alt="How much">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" id="title_howmuch">How much</h5>
|
||||
<p class="card-text" id="info_howmuch">
|
||||
how much
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="https://portal.amipro.me" target="_blank" class="btn btn-info" id="btn_portal" style="width:50%;margin-left: 25%;">Portal</a>
|
||||
<br><br>
|
||||
|
||||
<table width=100% style="text-align: center;">
|
||||
<tr>
|
||||
<td id="company_name">amiPro合同会社</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="company_open">2023年3月3日設立</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="company_addr">〒150-0001 東京都渋谷区神宮前六丁目23番4号 桑野ビル2階</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<!-- / Content -->
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="content-footer footer bg-footer-theme">
|
||||
<div class="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||
<div class="mb-2 mb-md-0">
|
||||
©
|
||||
<script>
|
||||
document.write(new Date().getFullYear());
|
||||
</script>
|
||||
<a href="https://www.amipro.me" target="_blank" class="footer-link fw-bolder">amiPro</a>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<a
|
||||
href="mailto:sales@amipro.me?subject=contact"
|
||||
|
||||
class="footer-link me-4"
|
||||
id="title_contact"
|
||||
>Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- / Footer -->
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
</div>
|
||||
<!-- Content wrapper -->
|
||||
</div>
|
||||
<!-- / Layout page -->
|
||||
</div>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="layout-overlay layout-menu-toggle"></div>
|
||||
</div>
|
||||
<!-- / Layout wrapper -->
|
||||
|
||||
<!-- div class="buy-now">
|
||||
<a
|
||||
href="https://themeselection.com/products/sneat-bootstrap-html-admin-template/"
|
||||
target="_blank"
|
||||
class="btn btn-danger btn-buy-now"
|
||||
>Upgrade to Pro</a
|
||||
>
|
||||
</div -->
|
||||
|
||||
<!-- Page JS -->
|
||||
|
||||
<!-- Place this tag in your head or just before your close body tag. -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
347
integration.html
Normal file
@@ -0,0 +1,347 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html
|
||||
lang="en-US"
|
||||
class="light-style"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
|
||||
<title> Integration - amiPro </title>
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-850DCHX9EJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-850DCHX9EJ');
|
||||
</script>
|
||||
|
||||
<meta name="description" content="the easiest to integrate Passkey cloud service" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="files/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Icons. Uncomment required icon fonts -->
|
||||
<link rel="stylesheet" href="files/boxicons.css?v=20230405" />
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="files/core.css" class="template-customizer-core-css" />
|
||||
<link rel="stylesheet" href="files/theme-default.css" class="template-customizer-theme-css" />
|
||||
<link rel="stylesheet" href="files/demo.css" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet" href="files/perfect-scrollbar.css" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="files/helpers.js"></script>
|
||||
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
<script src="files/config.js"></script>
|
||||
|
||||
<script src="files/jquery.js"></script>
|
||||
<script src="files/popper.js"></script>
|
||||
<script src="files/bootstrap.js"></script>
|
||||
<script src="files/perfect-scrollbar.js"></script>
|
||||
<script src="files/menu.js"></script>
|
||||
<script src="files/main.js"></script>
|
||||
|
||||
<script src="files/ua-parser.js"></script>
|
||||
|
||||
<script src="files/amipro_utils.js?v=20230401402"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var user_id, reg_session_id;
|
||||
|
||||
const i18n_messages = new Map();
|
||||
|
||||
var lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro - the easiest to integrate Passkeys cloud service");
|
||||
lang_map.set("zh-CN", "amiPro - 最易集成的Passkey云服务");
|
||||
lang_map.set("ja", "amiPro - 最も簡単に統合できるパスキー・クラウド・サービス");
|
||||
i18n_messages.set("label_welcome", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Sample site");
|
||||
lang_map.set("zh-CN", "示例网站");
|
||||
lang_map.set("ja", "サンプルサイト");
|
||||
i18n_messages.set("label_sample", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Contact us (sales@amipro.me)");
|
||||
lang_map.set("zh-CN", "联系我们(sales@amipro.me)");
|
||||
lang_map.set("ja", "お問い合わせ(sales@amipro.me)");
|
||||
i18n_messages.set("title_contact", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "How to integrate");
|
||||
lang_map.set("zh-CN", "如何集成");
|
||||
lang_map.set("ja", "統合方法");
|
||||
i18n_messages.set("label_integartion_title", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step1: Open sample site");
|
||||
lang_map.set("zh-CN", "步骤1: 打开示例网站");
|
||||
lang_map.set("ja", "ステップ1: サンプルサイトを開く");
|
||||
i18n_messages.set("btn_step1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Click the following link to enter the sample website, enter any user name and password, and log in to the website. In the following instructions you will need to refer to the source code of the sample website. <br><a href='https://sample.amipro.me/' target='_blank'>https://sample.amipro.me</a>");
|
||||
lang_map.set("zh-CN", "点击以下链接,进入示例网站,输入任意用户名和密码,登录网站。在以下的说明中您将需要参考示例网站的源代码。<br><a href='https://sample.amipro.me/' target='_blank'>https://sample.amipro.me</a>");
|
||||
lang_map.set("ja", "以下のリンクをクリックして、サンプルサイトに入り、任意のユーザー名とパスワードを入力して、サイトにログインしてください。以下の説明では、サンプルサイトのソースコードを参照する必要があります。<br><a href='https://sample.amipro.me/' target='_blank'>https://sample.amipro.me</a>");
|
||||
i18n_messages.set("info_top_step1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step2: Login page integration");
|
||||
lang_map.set("zh-CN", "步骤2: 登录页面集成");
|
||||
lang_map.set("ja", "ステップ2: ログインページの統合");
|
||||
i18n_messages.set("btn_step2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Use the amiPro JavaScript SDK to add passkey sign-in to your website's login page. <br>1. Download the amiPro SDK. <br><a href='https://sample.amipro.me/files/dfido2-lib.js' target='_blank'>dfido2-lib.js</a><br><a href='https://sample.amipro.me/files/amipro_utils.js' target='_blank'>amipro_utils.js</a><br>"+
|
||||
"2. In the <head> section, import the SDK with script tags specifying src.<br>3. Refer to the window.onload code in the sample site's <head> and add passkey login to your website's login page.<br><a href='https://sample.amipro.me/login.html' target='_blank'>https://sample.amipro.me/login.html</a>");
|
||||
lang_map.set("zh-CN", "使用 amiPro JavaScript SDK 为网站登录页面集成 Passkey 登录。<br>1. 下载 amiPro SDK。<br><a href='https://sample.amipro.me/files/dfido2-lib.js' target='_blank'>dfido2-lib.js</a><br><a href='https://sample.amipro.me/files/amipro_utils.js' target='_blank'>amipro_utils.js</a><br>"+
|
||||
"2. 在<head>部分使用带 src 的 script 标签引入 SDK。<br>3. 参考示例站点<head>中 window.onload 周边的代码,将 Passkey 登录集成到网站的登录页面。<br><a href='https://sample.amipro.me/login.html' target='_blank'>https://sample.amipro.me/login.html</a>");
|
||||
lang_map.set("ja", "amiPro JavaScript SDK を使用して、Web サイトのログインページにパスキー ログインを追加します。<br>1. amiPro SDK をダウンロードします。<br><a href='https://sample.amipro.me/files/dfido2-lib.js' target='_blank'>dfido2-lib.js</a><br><a href='https://sample.amipro.me/files/amipro_utils.js' target='_blank'>amipro_utils.js</a><br>"+
|
||||
"2. <head> セクションで src を指定した script タグで SDK を読み込みます。<br>3. サンプルサイトの <head> にある window.onload 周辺のコードを参照し、ログインページにパスキーログインを追加してください。<br><a href='https://sample.amipro.me/login.html' target='_blank'>https://sample.amipro.me/login.html</a>");
|
||||
i18n_messages.set("info_top_step2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step3: Build devices management page");
|
||||
lang_map.set("zh-CN", "步骤3: 构建设备管理页面");
|
||||
lang_map.set("ja", "ステップ3: デバイス管理ページの構築");
|
||||
i18n_messages.set("btn_step3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "The device management page provides two functions:<br>1. When the user loses or replaces a device such as a registered mobile phone, use the recovery link generated by the management portal to replace the device. <br>2. Users add and delete registered devices. <br>Please refer to the source code of the sample site to integrate the device management page into your website. <br><a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a><br> The code surrounding reg_session_id is the recovery link processing code.");
|
||||
lang_map.set("zh-CN", "设备管理页面提供两大功能:<br>1、当用户丢失或更换注册过的手机等设备时,使用管理门户生成的恢复链接替换设备。<br>2、用户追加以及删除注册的设备。<br>请参考示例站点的源代码,将设备管理页面集成到网站。<br><a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a><br>其中reg_session_id周边的代码为恢复链接处理代码。");
|
||||
lang_map.set("ja", "デバイス管理ページは2つ機能があります:<br>1. ユーザーが登録済みの携帯電話などのデバイスを紛失または交換した場合、管理ポータルによって生成されたリカバリー・リンクを使用してデバイスを更新する機能。 <br>2. ユーザーはデバイスを追加および削除する機能。 <br>デバイス管理ページを Web サイトに統合するには、サンプル サイトのソース コードを参照してください。 <br><a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a><br>この中に reg_session_id 周辺のコードはリカバリ・リンクの処理コードです。");
|
||||
i18n_messages.set("info_top_step3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step4: Session management");
|
||||
lang_map.set("zh-CN", "步骤4: 会话管理");
|
||||
lang_map.set("ja", "ステップ4: セッション管理");
|
||||
i18n_messages.set("btn_step4", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "There are two methods of session management:<br>Method 1. Use amiPro's validSession API to manage sessions. Refer to the setSessionStatus function in <a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a>. <br>Method 2: Use your website's original session management, just call amiPro's logoutFido2UserSession function in your website's original session timeout processing.");
|
||||
lang_map.set("zh-CN", "会话管理有两种方式:<br>方式1、使用amiPro的validSession API 管理会话。参考<a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a>中的setSessionStatus函数。<br>方式2、使用您的网站原有的会话管理,只需在您的网站原有的会话超时的处理中调用amiPro的logoutFido2UserSession函数。");
|
||||
lang_map.set("ja", "セッション管理は2つ方法があります:<br>方法 1: amiPro の validSession API を使用してセッションを管理します。<a href='https://sample.amipro.me/devices.html' target='_blank'>https://sample.amipro.me/devices.html</a>にあるsetSessionStatus関数を参考してください。 <br>方法 2: Web サイトの既存のセッション管理を使用します。Web サイトの既存のセッションのタイムアウト処理中、 amiPro の logoutFido2UserSession 関数を呼び出すだけで管理出来ます。");
|
||||
i18n_messages.set("info_top_step4", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step5: Management Portal registration");
|
||||
lang_map.set("zh-CN", "步骤5: 管理门户注册");
|
||||
lang_map.set("ja", "ステップ5: 管理ポータル登録");
|
||||
i18n_messages.set("btn_step5", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Use your email address to register amiPro management portal for free:<br>1. Please use the PC and other devices you plan to manage amiPro and open the following link with your browser. <br><a href='https://portal.amipro.me/'>https://portal.amipro.me</a><br>2. In the management portal, enter your email address and click the [Create a new account or add a new device] link. <br>3. Use the same browser to open the link in the email you received and add the device<br>4. Click [Go to top page] and use the added device [Passkey Login].<br><img src='files/portal_reg_jp.jpg' width=50%>");
|
||||
lang_map.set("zh-CN", "使用您的邮件地址免费注册amiPro管理门户: <br>1、请用您准备管理amiPro的PC等设备及其浏览器打开以下链接。<br><a href='https://portal.amipro.me/'>https://portal.amipro.me</a><br>2、在管理门户中,输入您的邮件地址并点击【创建新账号或添加新设备】链接。<br>3、使用相同的浏览器打开您收到的邮件中的链接并添加设备<br>4、点击【去首页】,使用添加的设备【Passkey登录】进入管理门户。<br><img src='files/portal_reg_jp.jpg' width=50%>");
|
||||
lang_map.set("ja", "電子メール アドレスを使用して、amiPro 管理ポータルに無料でサインアップします: <br>1. amiPro を管理する予定の PC およびその他のデバイスを使用し、ブラウザで次のリンクを開いてください。 <br><a href='https://portal.amipro.me/'>https://portal.amipro.me</a><br>2. 管理ポータルで、電子メール アドレスを入力し、[アカウントを作成・新しいデバイスを追加] リンクをクリックしてください。 <br>3. 受信した電子メールにあるURLを同じブラウザで開いてデバイスを追加してください。<br>4. [トップページへ] をクリックして、登録したデバイスで[パスキーでログイン]でログインして、トップページへ。<br><img src='files/portal_reg_jp.jpg' width=50%>");
|
||||
i18n_messages.set("info_top_step5", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Step6: FIDO2 server settings");
|
||||
lang_map.set("zh-CN", "步骤6: FIDO2服务器设置");
|
||||
lang_map.set("ja", "ステップ6: FIDO2 サーバー設定");
|
||||
i18n_messages.set("btn_step6", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Click [Settings] on the Portal left menu, and then click [Add] on the right page. Enter your website domain name (the port number cannot be included), and note that your website needs to use the HTTPS protocol. <br>【Device registration page】is the link to the device management page built by step 3.<br>Click [Submit] to complete the settings.<br><img src='files/portal_conf_jp.jpg' width=80%>");
|
||||
lang_map.set("zh-CN", "点击管理门户左侧菜单中的【设定】,之后点击右侧页面中的【添加】。输入您的网站域名(不能包含端口号),注意您的网站需要使用HTTPS协议。<br>【设备注册页面】为步骤3构建的设备管理页面的链接。<br>最后需要点击【提 交】完成设定。<br><img src='files/portal_conf_jp.jpg' width=80%>");
|
||||
lang_map.set("ja", "管理ポータル左メニューの[設定]をクリックし、右ページの[追加]をクリックしてください。 Web サイトのドメイン名を入力します (ポート番号は含めることはできません)。Web サイトでは HTTPS プロトコルを使用する必要があることに注意してください。 <br>【デバイス登録ページ】は手順3で作成したデバイス管理ページへのリンクです。<br>最後は送信をクリックして設定完了<br><img src='files/portal_conf_jp.jpg' width=80%>");
|
||||
i18n_messages.set("info_top_step6", lang_map);
|
||||
|
||||
window.onload = async function() {
|
||||
setI18NText(i18n_messages)
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout wrapper -->
|
||||
<div class="layout-wrapper layout-content-navbar">
|
||||
<div class="layout-container">
|
||||
<!-- Layout container -->
|
||||
<div class="layout-page">
|
||||
<!-- Navbar -->
|
||||
|
||||
<nav
|
||||
class="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
|
||||
id="layout-navbar"
|
||||
>
|
||||
|
||||
|
||||
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
|
||||
<div class="navbar-nav align-items-center">
|
||||
<div class="nav-item d-flex align-items-center">
|
||||
<img src="files/favicon.ico" alt="amiPro" width="80%">
|
||||
<span id="label_welcome" style="padding-left: 60px;white-space: nowrap; font-size: x-large; color: #000000;" class="d-none d-lg-block"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://sample.amipro.me" target="_blank" style="width: 100%; text-align: right;">
|
||||
<i class="bx bx-link bx-sm"></i>
|
||||
<span id="label_sample"> Sample</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- / Navbar -->
|
||||
|
||||
<!-- Content wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content -->
|
||||
<div style="margin: 20px;">
|
||||
<small class="text-normal fw-semibold" id="label_integartion_title">Integration</small>
|
||||
|
||||
<div class="accordion mt-3">
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="headingOne">
|
||||
<button id="btn_step1" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordionOne" aria-expanded="false" aria-controls="accordionOne">
|
||||
Sample site
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse collapse" style="">
|
||||
<div class="accordion-body" id="info_top_step1">
|
||||
Sample site
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="headingTwo">
|
||||
<button id="btn_step2" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordionTwo" aria-expanded="false" aria-controls="accordionTwo">
|
||||
Login integration
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordionTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" style="">
|
||||
<div class="accordion-body" id="info_top_step2">
|
||||
Login integration
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="headingThree">
|
||||
<button id="btn_step3" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordionThree" aria-expanded="false" aria-controls="accordionThree">
|
||||
Device mng page
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordionThree" class="accordion-collapse collapse" aria-labelledby="headingThree" style="">
|
||||
<div class="accordion-body" id="info_top_step3">
|
||||
Device mng page
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="heading4">
|
||||
<button id="btn_step4" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordion4" aria-expanded="false" aria-controls="accordion4">
|
||||
Session mag
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordion4" class="accordion-collapse collapse" aria-labelledby="heading4" style="">
|
||||
<div class="accordion-body" id="info_top_step4">
|
||||
Session mag
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="heading5">
|
||||
<button id="btn_step5" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordion5" aria-expanded="false" aria-controls="accordion5">
|
||||
Session mag
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordion5" class="accordion-collapse collapse" aria-labelledby="heading5" style="">
|
||||
<div class="accordion-body" id="info_top_step5">
|
||||
Session mag
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card accordion-item">
|
||||
<h2 class="accordion-header" id="heading6">
|
||||
<button id="btn_step6" type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordion6" aria-expanded="false" aria-controls="accordion6">
|
||||
Session mag
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordion6" class="accordion-collapse collapse" aria-labelledby="heading6" style="">
|
||||
<div class="accordion-body" id="info_top_step6">
|
||||
Session mag
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
</div>
|
||||
<!-- / Content -->
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="content-footer footer bg-footer-theme">
|
||||
<div class="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||
<div class="mb-2 mb-md-0">
|
||||
©
|
||||
<script>
|
||||
document.write(new Date().getFullYear());
|
||||
</script>
|
||||
<a href="https://www.amipro.me" target="_blank" class="footer-link fw-bolder">amiPro</a>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<a
|
||||
href="mailto:sales@amipro.me?subject=contact"
|
||||
|
||||
class="footer-link me-4"
|
||||
id="title_contact"
|
||||
>Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- / Footer -->
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
</div>
|
||||
<!-- Content wrapper -->
|
||||
</div>
|
||||
<!-- / Layout page -->
|
||||
</div>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="layout-overlay layout-menu-toggle"></div>
|
||||
</div>
|
||||
<!-- / Layout wrapper -->
|
||||
|
||||
<!-- div class="buy-now">
|
||||
<a
|
||||
href="https://themeselection.com/products/sneat-bootstrap-html-admin-template/"
|
||||
target="_blank"
|
||||
class="btn btn-danger btn-buy-now"
|
||||
>Upgrade to Pro</a
|
||||
>
|
||||
</div -->
|
||||
|
||||
<!-- Page JS -->
|
||||
|
||||
<!-- Place this tag in your head or just before your close body tag. -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
318
merits.html
Normal file
@@ -0,0 +1,318 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html
|
||||
lang="en-US"
|
||||
class="light-style"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
|
||||
<title> Passkeys - amiPro </title>
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-850DCHX9EJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-850DCHX9EJ');
|
||||
</script>
|
||||
|
||||
<meta name="description" content="the easiest to integrate Passkey cloud service" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="files/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Icons. Uncomment required icon fonts -->
|
||||
<link rel="stylesheet" href="files/boxicons.css?v=20230405" />
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="files/core.css" class="template-customizer-core-css" />
|
||||
<link rel="stylesheet" href="files/theme-default.css" class="template-customizer-theme-css" />
|
||||
<link rel="stylesheet" href="files/demo.css" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet" href="files/perfect-scrollbar.css" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="files/helpers.js"></script>
|
||||
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
<script src="files/config.js"></script>
|
||||
|
||||
<script src="files/jquery.js"></script>
|
||||
<script src="files/popper.js"></script>
|
||||
<script src="files/bootstrap.js"></script>
|
||||
<script src="files/perfect-scrollbar.js"></script>
|
||||
<script src="files/menu.js"></script>
|
||||
<script src="files/main.js"></script>
|
||||
|
||||
<script src="files/ua-parser.js"></script>
|
||||
|
||||
<script src="files/amipro_utils.js?v=20230401402"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var user_id, reg_session_id;
|
||||
|
||||
const i18n_messages = new Map();
|
||||
|
||||
var lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro - the easiest to integrate Passkeys cloud service");
|
||||
lang_map.set("zh-CN", "amiPro - 最易集成的Passkey云服务");
|
||||
lang_map.set("ja", "amiPro - 最も簡単に統合できるパスキー・クラウド・サービス");
|
||||
i18n_messages.set("label_welcome", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Management Portal");
|
||||
lang_map.set("zh-CN", "管理门户");
|
||||
lang_map.set("ja", "管理ポータル");
|
||||
i18n_messages.set("label_portal", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Contact us(sales@amipro.me)");
|
||||
lang_map.set("zh-CN", "联系我们(sales@amipro.me)");
|
||||
lang_map.set("ja", "お問い合わせ(sales@amipro.me)");
|
||||
i18n_messages.set("title_contact", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Higher security");
|
||||
lang_map.set("zh-CN", "更高的安全性");
|
||||
lang_map.set("ja", "より高いセキュリティ");
|
||||
i18n_messages.set("info_title_1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey authentication provides higher security than password-based authentication through stronger authentication methods, risk elimination, and phishing attack prevention.<br>* <b>Stronger authentication methods</b>: Passwords are subject to the risk of being guessed or stolen by others. In contrast, Passkey authentication uses stronger authentication factors such as biometrics (fingerprint, face recognition) or hardware keys (security keys, smart cards), which can better protect users' personal information from unauthorized access.<br>"+
|
||||
"* <b>Elimination of password risks</b>: Passwords need to be selected and managed by users. However, in many cases, users do not choose strong passwords and tend to use the same password for multiple services. This exposes the risk that if a password is leaked, many accounts may be compromised. Passkey authentication eliminates such risks.<br>"+
|
||||
"* <b>Countermeasures against phishing</b>: Phishing attacks are fraudulent methods that attempt to obtain passwords from users using fake websites or emails. With Passkey authentication, users do not need to enter passwords to authenticate, so they are less likely to be targeted by phishing attacks.");
|
||||
lang_map.set("zh-CN", "Passkey认证通过更强的认证方式、风险排除、防止钓鱼攻击等,提供比基于密码的认证更高的安全性。<br>* <b>更强的认证方式</b>:密码容易被他人猜测或盗取。相比之下,Passkey认证使用生物特征(指纹、面部识别)或硬件密钥(安全密钥、智能卡)等更强的认证因素,可以更好地保护用户的个人信息免受未经授权的访问。<br>"+
|
||||
"* <b>排除密码风险</b>:密码需要用户自行选择和管理。但是,在许多情况下,用户不会选择强密码,并且倾向于在多个服务中使用相同的密码。这会导致密码泄露的风险,可能会危及许多帐户。Passkey认证消除了这些风险。<br>"+
|
||||
"* <b>钓鱼攻击的对策</b>:钓鱼攻击是一种使用假网站或电子邮件试图从用户那里获取密码的欺诈性方法。Passkey认证不需要用户输入密码进行认证,因此不太可能成为钓鱼攻击的目标。");
|
||||
lang_map.set("ja", "パスキー認証は、より強力な認証手段やリスクの排除、フィッシング攻撃への対策などを通じて、パスワードベースの認証よりも高いセキュリティを提供します。<br><br>* <b>強力な認証手段</b>:パスワードは、他人に推測されたり盗まれたりするリスクがあります。一方、パスキー認証では、生体認証(指紋、顔認識)やハードウェアキー(セキュリティキー、スマートカード)など、より強力な認証要素が使用されます。これにより、ユーザーの個人情報を不正なアクセスからより安全に保護できます。<br>"+
|
||||
"* <b>パスワードリスクの排除</b>:パスワードはユーザーによって選択され、管理される必要があります。しかし、多くの場合、ユーザーは強力なパスワードを選択せず、同じパスワードを複数のサービスで使用する傾向があります。これにより、パスワードが漏洩した場合、多くのアカウントが危険にさらされる可能性があります。パスキー認証では、このようなリスクが排除されます。<br>"+
|
||||
"* <b>フィッシングへの対抗策</b>:フィッシング攻撃は、偽のウェブサイトやメールを使用してユーザーからパスワードを入手しようとする詐欺的な手法です。パスキー認証では、ユーザーが認証を行うためにパスワードを入力する必要がないため、フィッシング攻撃の対象となる可能性が低くなります。");
|
||||
i18n_messages.set("info_1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Increase website value");
|
||||
lang_map.set("zh-CN", "网站价值的提高");
|
||||
lang_map.set("ja", "ウェブサイトの価値向上");
|
||||
i18n_messages.set("info_title_2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey authentication can increase the value of a website through factors such as convenience, security, account protection, and user satisfaction.<br>* <b>Improved convenience</b>: Passkey authentication eliminates the hassle of users remembering or entering passwords. Instead, authentication can be done with simple means such as biometrics (fingerprint, face recognition) or hardware keys (security keys, smart cards). This improves the user experience and increases the convenience of the website.<br>"+
|
||||
"* <b>Enhanced security</b>: Passkey authentication enhances the security of a website by using stronger authentication factors. Biometrics and hardware keys are more complex and less likely to be stolen than passwords, and are also resistant to phishing attacks. This improves the security level of the website and increases user trust.<br>"+
|
||||
"* <b>Account protection</b>: Passkey authentication eliminates the risks associated with passwords (use of weak passwords, reuse, leakage, etc.). This enhances the protection of user accounts and reduces the risk of unauthorized access and data leakage.<br>"+
|
||||
"* <b>Improved user satisfaction</b>: Passkey authentication eliminates the hassle of managing passwords and resetting forgotten passwords. Users can easily and securely access the website, reducing stress and frustration. This improves user satisfaction and may increase user loyalty and frequency of use of the website.");
|
||||
lang_map.set("zh-CN", "Passkey认证可以通过诸如便利性、安全性、帐户保护和用户满意度等因素来提高网站的价值。<br>* <b>提高便利性</b>:Passkey认证消除了用户记住或输入密码的麻烦。相反,可以使用生物特征(指纹、面部识别)或硬件密钥(安全密钥、智能卡)等简单方法进行认证。这提高了用户体验,增加了网站的便利性。<br>"+
|
||||
"* <b>增强安全性</b>:Passkey认证通过使用更强的认证因素来增强网站的安全性。生物特征和硬件密钥比密码更复杂,更不容易被盗,也更抵御钓鱼攻击。这提高了网站的安全级别,增加了用户的信任。<br>"+
|
||||
"* <b>帐户保护</b>:Passkey认证消除了与密码相关的风险(使用弱密码、重用、泄漏等)。这增强了用户帐户的保护,降低了未经授权的访问和数据泄漏的风险。<br>"+
|
||||
"* <b>提高用户满意度</b>:Passkey认证消除了管理密码和重置忘记密码的麻烦。用户可以轻松安全地访问网站,减少压力和挫折感。这提高了用户的满意度,可能会增加用户对网站的忠诚度和使用频率。");
|
||||
lang_map.set("ja", "パスキー認証は、利便性、セキュリティ、アカウント保護、ユーザー満足度の向上などの要素を通じて、ウェブサイトの価値向上に貢献することができます。<br><br>*<b>利便性の向上</b>: パスキー認証は、ユーザーがパスワードを覚えたり入力したりする手間を省くことができます。代わりに、生体認証(指紋、顔認識)やハードウェアキー(セキュリティキー、スマートカード)などの簡単な手段で認証が可能となります。これにより、ユーザーエクスペリエンスが向上し、ウェブサイトの利便性が高まります。<br>"+
|
||||
"*<b>セキュリティの強化</b>: パスキー認証は、より強力な認証要素を使用するため、ウェブサイトのセキュリティを強化します。生体認証やハードウェアキーは、パスワードよりも難解で盗まれにくいですし、フィッシング攻撃にも強いです。これにより、ウェブサイトのセキュリティレベルが向上し、ユーザーの信頼を高めることができます。<br>"+
|
||||
"*<b>アカウントの保護</b>: パスキー認証では、パスワードに関連するリスク(弱いパスワードの使用、再利用、漏洩など)を排除することができます。これにより、ユーザーアカウントの保護が強化され、不正アクセスやデータの漏洩リスクが低減します。<br>"+
|
||||
"*<b>ユーザーの満足度向上</b>: パスキー認証は、煩雑なパスワード管理や忘れたパスワードのリセットの手間を省くことができます。ユーザーがウェブサイトに簡単かつ安全にアクセスできるため、ストレスやフラストレーションが軽減されます。これにより、ユーザーの満足度が向上し、ウェブサイトへの忠誠心や利用頻度が増加する可能性があります。");
|
||||
i18n_messages.set("info_2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Reduce operating costs");
|
||||
lang_map.set("zh-CN", "降低运营成本");
|
||||
lang_map.set("ja", "運用コストの低減");
|
||||
i18n_messages.set("info_title_3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey authentication can reduce operating costs through factors such as reduced password reset, reduced security incidents, and simplified security management.<br>* <b>Reduced password reset</b>: With Passkey authentication, users do not need to remember or reset passwords. This reduces the number of password reset requests and responses to user support, which may reduce operating costs.<br>"+
|
||||
"* <b>Reduced security incidents</b>: Password-based authentication has risks such as the use or reuse of weak passwords and password leakage. This increases the likelihood of security incidents such as unauthorized access and data leakage. Passkey authentication reduces these risks, which may reduce operating costs associated with security incidents.<br>"+
|
||||
"* <b>Simplified security management</b>: Passkey authentication reduces tasks related to password management and storage. Passwords require encryption and secure storage, and it is recommended to regularly manage and change password policies. In contrast, Passkey authentication uses simpler security elements (biometrics or hardware keys), which may simplify security management.");
|
||||
lang_map.set("zh-CN", "Passkey认证可以通过减少密码重置、减少安全事件和简化安全管理等因素来降低运营成本。<br>* <b>减少密码重置</b>:Passkey认证不需要用户记住或重置密码。这减少了密码重置请求和对用户支持的响应,可能会降低运营成本。<br>"+
|
||||
"* <b>减少安全事件</b>:基于密码的认证存在使用或重用弱密码和密码泄漏等风险。这会增加未经授权的访问和数据泄漏等安全事件发生的可能性。Passkey认证减少了这些风险,这可能会降低与安全事件相关的运营成本。<br>"+
|
||||
"* <b>简化安全管理</b>:Passkey认证减少了与密码管理和存储相关的任务。密码需要加密和安全存储,并且建议定期管理和更改密码策略。相比之下,Passkey认证使用更简单的安全元素(生物特征或硬件密钥),这可能会简化安全管理。");
|
||||
lang_map.set("ja", "パスキー認証は、パスワードのリセットの削減、セキュリティインシデントの削減、セキュリティ管理の簡素化などの要素を通じて、運用コストを削減することができます。<br><br>*<b>パスワードリセットの削減</b>: パスキー認証では、ユーザーがパスワードを覚えたりリセットしたりする必要がありません。これにより、パスワードリセットの要求やユーザーサポートへの対応が削減され、運用コストが削減されます。<br>"+
|
||||
"*<b>セキュリティインシデントの削減</b>: パスワードベースの認証には、弱いパスワードの使用や再利用、パスワードの漏洩などのリスクがあります。これにより、不正アクセスやデータの漏洩などのセキュリティインシデントが発生する可能性が高まります。パスキー認証は、これらのリスクを低減することで、セキュリティインシデントに関連する運用コストを削減することができます。<br>"+
|
||||
"*<b>セキュリティ管理の簡素化</b>: パスキー認証は、パスワード管理や保存に関連するタスクを削減します。パスワードは暗号化と安全な保存が必要であり、定期的なパスワードポリシーの管理と変更が推奨されています。これに対し、パスキー認証では、よりシンプルなセキュリティ要素(生体認証やハードウェアキー)を使用するため、セキュリティ管理の簡素化につながります。");
|
||||
i18n_messages.set("info_3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Effect analysis");
|
||||
lang_map.set("zh-CN", "效果分析");
|
||||
lang_map.set("ja", "効果分析");
|
||||
i18n_messages.set("info_title_4", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "According to the research of a leading company in the industry, Passkey is:<br>* Reduced phishing and credential theft:<b>99.9</b>%<br>* ROI over 3 years:<b>203</b>%<br>* Reduction of help desk tickets in the 3rd year:<b>75</b>%");
|
||||
lang_map.set("zh-CN", "根据业界领先公司的研究,Passkey是:<br>* 减少网络钓鱼和凭证盗窃:<b>99.9</b>%<br>* 3年内的投资回报率:<b>203</b>%<br>* 第3年的帮助台票据减少:<b>75</b>%");
|
||||
lang_map.set("ja", "業界大手のリサーチより、パスキーは:<br>* フィッシングや認証情報の盗難の減少:<b>99.9</b>%<br>* 3 年後のROI:<b>203</b>%<br>* 3 年目のヘルプデスク チケットの削減:<b>75</b>%");
|
||||
i18n_messages.set("info_4", lang_map);
|
||||
|
||||
window.onload = async function() {
|
||||
setI18NText(i18n_messages)
|
||||
|
||||
var video = document.getElementById('video');
|
||||
video.src = "files/amiProSampleSite01-JP.mp4";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout wrapper -->
|
||||
<div class="layout-wrapper layout-content-navbar">
|
||||
<div class="layout-container">
|
||||
<!-- Layout container -->
|
||||
<div class="layout-page">
|
||||
<!-- Navbar -->
|
||||
|
||||
<nav
|
||||
class="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
|
||||
id="layout-navbar"
|
||||
>
|
||||
|
||||
|
||||
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
|
||||
<div class="navbar-nav align-items-center">
|
||||
<div class="nav-item d-flex align-items-center">
|
||||
<img src="files/favicon.ico" alt="amiPro" width="80%">
|
||||
<span id="label_welcome" style="padding-left: 60px;white-space: nowrap; font-size: x-large; color: #000000;" class="d-none d-lg-block"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://portal.amipro.me" target="_blank" style="width: 100%; text-align: right;">
|
||||
<i class="bx bx-link bx-sm"></i>
|
||||
<span id="label_portal">Portal</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- / Navbar -->
|
||||
|
||||
<!-- Content wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content -->
|
||||
<div style="margin: 20px;">
|
||||
|
||||
<div class="accordion mt-3">
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_1" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_1">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_2" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_2">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_3" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_3">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_4" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_4">
|
||||
define
|
||||
</div>
|
||||
<br>
|
||||
<img src="files/YubicoResearch.jpg" width="80%">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<video id="video" width="100%" height="auto" controls="controls" preload="auto" style="margin: 10px;">
|
||||
<source src="" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
</div>
|
||||
<!-- / Content -->
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="content-footer footer bg-footer-theme">
|
||||
<div class="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||
<div class="mb-2 mb-md-0">
|
||||
©
|
||||
<script>
|
||||
document.write(new Date().getFullYear());
|
||||
</script>
|
||||
<a href="https://www.amipro.me" target="_blank" class="footer-link fw-bolder">amiPro</a>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<a
|
||||
href="mailto:sales@amipro.me?subject=contact"
|
||||
|
||||
class="footer-link me-4"
|
||||
id="title_contact"
|
||||
>Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- / Footer -->
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
</div>
|
||||
<!-- Content wrapper -->
|
||||
</div>
|
||||
<!-- / Layout page -->
|
||||
</div>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="layout-overlay layout-menu-toggle"></div>
|
||||
</div>
|
||||
<!-- / Layout wrapper -->
|
||||
|
||||
<!-- div class="buy-now">
|
||||
<a
|
||||
href="https://themeselection.com/products/sneat-bootstrap-html-admin-template/"
|
||||
target="_blank"
|
||||
class="btn btn-danger btn-buy-now"
|
||||
>Upgrade to Pro</a
|
||||
>
|
||||
</div -->
|
||||
|
||||
<!-- Page JS -->
|
||||
|
||||
<!-- Place this tag in your head or just before your close body tag. -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
288
passkey.html
Normal file
@@ -0,0 +1,288 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html
|
||||
lang="en-US"
|
||||
class="light-style"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
|
||||
<title> Passkeys - amiPro </title>
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-850DCHX9EJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-850DCHX9EJ');
|
||||
</script>
|
||||
|
||||
<meta name="description" content="the easiest to integrate Passkey cloud service" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="files/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Icons. Uncomment required icon fonts -->
|
||||
<link rel="stylesheet" href="files/boxicons.css?v=20230405" />
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="files/core.css" class="template-customizer-core-css" />
|
||||
<link rel="stylesheet" href="files/theme-default.css" class="template-customizer-theme-css" />
|
||||
<link rel="stylesheet" href="files/demo.css" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet" href="files/perfect-scrollbar.css" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="files/helpers.js"></script>
|
||||
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
<script src="files/config.js"></script>
|
||||
|
||||
<script src="files/jquery.js"></script>
|
||||
<script src="files/popper.js"></script>
|
||||
<script src="files/bootstrap.js"></script>
|
||||
<script src="files/perfect-scrollbar.js"></script>
|
||||
<script src="files/menu.js"></script>
|
||||
<script src="files/main.js"></script>
|
||||
|
||||
<script src="files/ua-parser.js"></script>
|
||||
|
||||
<script src="files/amipro_utils.js?v=20230401402"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var user_id, reg_session_id;
|
||||
|
||||
const i18n_messages = new Map();
|
||||
|
||||
var lang_map = new Map();
|
||||
lang_map.set("en-US", "amiPro - the easiest to integrate Passkeys cloud service");
|
||||
lang_map.set("zh-CN", "amiPro - 最易集成的Passkey云服务");
|
||||
lang_map.set("ja", "amiPro - 最も簡単に統合できるパスキー・クラウド・サービス");
|
||||
i18n_messages.set("label_welcome", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Management Portal");
|
||||
lang_map.set("zh-CN", "管理门户");
|
||||
lang_map.set("ja", "管理ポータル");
|
||||
i18n_messages.set("label_portal", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Contact us (sales@amipro.me)");
|
||||
lang_map.set("zh-CN", "联系我们(sales@amipro.me)");
|
||||
lang_map.set("ja", "お問い合わせ(sales@amipro.me)");
|
||||
i18n_messages.set("title_contact", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey definition");
|
||||
lang_map.set("zh-CN", "Passkey 的定义");
|
||||
lang_map.set("ja", "パスキーの定義");
|
||||
i18n_messages.set("info_title_1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "A passkey is a method of user authentication that eliminates the need for usernames and passwords. It also helps prevent security lapses and attacks.<br><a href='https://en.wikipedia.org/wiki/Passkey_(authentication)' target='_blank'>Wikipedia</a>");
|
||||
lang_map.set("zh-CN", "Passkey(通行密钥)是一种无需用户名和密码的用户身份验证方式,同时有助于防止安全漏洞和攻击。<br><a href='https://en.wikipedia.org/wiki/Passkey_(authentication)' target='_blank'>Wikipedia</a>");
|
||||
lang_map.set("ja", "パスキー(Passkeys, Passkey Authentication)は、パスワードに代わるより安全、迅速かつ使いやすい、パスワードレス認証に用いられる方式です。<br><a href='https://ja.wikipedia.org/wiki/パスキー' target='_blank'>Wikipedia</a>");
|
||||
i18n_messages.set("info_1", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey basics");
|
||||
lang_map.set("zh-CN", "Passkey 的基本用法");
|
||||
lang_map.set("ja", "パスキーの基本的な使い方");
|
||||
i18n_messages.set("info_title_2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "1. (Optional) If users already have an account with a user ID and password, they first sign in to the website<br>2. Register an authentication device using face or fingerprint<br>3. Next time, sign in with face or fingerprint—no password needed");
|
||||
lang_map.set("zh-CN", "1、(可选)已使用用户ID和密码注册的用户先登录网站<br>2、使用面部或指纹注册认证设备<br>3、下次登录时仅需进行面部或指纹认证即可进入网站");
|
||||
lang_map.set("ja", "1(任意):ユーザーIDとパスワードで登録済みのユーザーは、まずサイトにログインします<br>2 顔認証または指紋認証で認証デバイスを登録します<br>3 次回以降は顔認証または指紋認証だけでログインできます");
|
||||
i18n_messages.set("info_2", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey case studies");
|
||||
lang_map.set("zh-CN", "Passkey 的引入案例");
|
||||
lang_map.set("ja", "パスキーの導入事例");
|
||||
i18n_messages.set("info_title_3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "<b>Google</b>:<a href='https://wired.jp/article/google-passkey-password-replacement/' target='_blank'>Google is fully introducing the authentication method \"Passkey\"</a><br><b>Mercari</b>:<a href='https://about.mercari.com/press/news/articles/20230414_passkeys/' target='_blank'>Flea market app \"Mercari\" supports biometric authentication \"Passkey\" that does not require a password</a><br><b>Docomo</b>:<a href='https://www.bcnretail.com/market/detail/20221018_300507.html' target='_blank'>d Account to introduce new authentication methods for web authentication and passkeys for login</a>");
|
||||
lang_map.set("zh-CN", "<b>Google</b>:<a href='https://wired.jp/article/google-passkey-password-replacement/' target='_blank'>谷歌正式推出“Passkey”认证方式</a><br><b>Mercari</b>:<a href='https://about.mercari.com/press/news/articles/20230414_passkeys/' target='_blank'>跳蚤市场应用“Mercari”支持无需密码的生物识别认证“Passkey”</a><br><b>Docomo</b>:<a href='https://www.bcnretail.com/market/detail/20221018_300507.html' target='_blank'>d Account将引入Web认证和Passkey的新认证方式以登录</a>");
|
||||
lang_map.set("ja", "<b>Google</b>:<a href='https://wired.jp/article/google-passkey-password-replacement/' target='_blank'>認証方式「パスキー」をグーグルが本格導入</a><br><b>メルカリ</b>:<a href='https://about.mercari.com/press/news/articles/20230414_passkeys/' target='_blank'>フリマアプリ「メルカリ」、パスワード不要な生体認証「パスキー」に対応</a><br><b>ドコモ</b>:<a href='https://www.bcnretail.com/market/detail/20221018_300507.html' target='_blank'>dアカウントのログインにWeb認証とパスキーによる新たな認証手段を導入へ</a>");
|
||||
i18n_messages.set("info_3", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "Passkey system architecture");
|
||||
lang_map.set("zh-CN", "Passkey 的系统架构");
|
||||
lang_map.set("ja", "パスキーのシステムアーキテクチャ");
|
||||
i18n_messages.set("info_title_4", lang_map);
|
||||
|
||||
lang_map = new Map();
|
||||
lang_map.set("en-US", "A: Mobile device browser <br>B: Computer browser <br>C: Mobile device App (App embeds amiPro SDK) <br>D: Your website <br>E: amiPro cloud service<br><br>1. The browser downloads the amiPro JavaScript SDK from your website (App does not need this step)<br>2. The browser and App call the amiPro cloud service through the SDK for authentication<br>3. amiPro returns the authentication result to your server<br><img src='files/amipro_sys.jpg' style='width: 80%;'>");
|
||||
lang_map.set("zh-CN", "A:移动设备浏览器 <br>B:电脑浏览器 <br>C:移动设备App(App嵌入amiPro SDK) <br>D:您的网站 <br>E:amiPro云服务<br><br>1、浏览器从您的网站下载amiPro JavaScript SDK(App无需此步骤)<br>2、浏览器及App通过SDK调用amiPro云服务进行认证<br>3、amiPro将认证结果返回给您的服务器<img src='files/amipro_sys.jpg' style='width: 80%;'>");
|
||||
lang_map.set("ja", "A:モバイルデバイスブラウザ<br>B:コンピュータブラウザ<br>C:モバイルデバイスアプリ(AppにamiPro SDKを埋め込む)<br>D:あなたのウェブサイト E:amiProクラウド・サービス<br><br>1、ブラウザはあなたのウェブサイトからamiPro JavaScript SDKをダウンロードします(Appはこのステップは必要ありません)<br>2、ブラウザとアプリはSDKを介してamiProクラウド・サービスを呼び出して認証します<br>3、amiProは認証結果をあなたのサーバーに返します<br><img src='files/amipro_sys.jpg' style='width: 80%;'>");
|
||||
i18n_messages.set("info_4", lang_map);
|
||||
|
||||
window.onload = async function() {
|
||||
setI18NText(i18n_messages)
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout wrapper -->
|
||||
<div class="layout-wrapper layout-content-navbar">
|
||||
<div class="layout-container">
|
||||
<!-- Layout container -->
|
||||
<div class="layout-page">
|
||||
<!-- Navbar -->
|
||||
|
||||
<nav
|
||||
class="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
|
||||
id="layout-navbar"
|
||||
>
|
||||
|
||||
|
||||
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
|
||||
<div class="navbar-nav align-items-center">
|
||||
<div class="nav-item d-flex align-items-center">
|
||||
<img src="files/favicon.ico" alt="amiPro" width="80%">
|
||||
<span id="label_welcome" style="padding-left: 60px;white-space: nowrap; font-size: x-large; color: #000000;" class="d-none d-lg-block"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://portal.amipro.me" target="_blank" style="width: 100%; text-align: right;">
|
||||
<i class="bx bx-link bx-sm"></i>
|
||||
<span id="label_portal">Portal</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- / Navbar -->
|
||||
|
||||
<!-- Content wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content -->
|
||||
<div style="margin: 20px;">
|
||||
|
||||
<div class="accordion mt-3">
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_1" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_1">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_2" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_2">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_3" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_3">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card accordion-item">
|
||||
<h5 class="accordion-header" id="info_title_4" style="margin: 10px;">
|
||||
define
|
||||
</h5>
|
||||
|
||||
<div id="accordionOne" class="accordion-collapse ">
|
||||
<div class="accordion-body" id="info_4">
|
||||
define
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
</div>
|
||||
<!-- / Content -->
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="content-footer footer bg-footer-theme">
|
||||
<div class="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||
<div class="mb-2 mb-md-0">
|
||||
©
|
||||
<script>
|
||||
document.write(new Date().getFullYear());
|
||||
</script>
|
||||
<a href="https://www.amipro.me" target="_blank" class="footer-link fw-bolder">amiPro</a>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<a
|
||||
href="mailto:sales@amipro.me?subject=contact"
|
||||
|
||||
class="footer-link me-4"
|
||||
id="title_contact"
|
||||
>Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- / Footer -->
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
</div>
|
||||
<!-- Content wrapper -->
|
||||
</div>
|
||||
<!-- / Layout page -->
|
||||
</div>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="layout-overlay layout-menu-toggle"></div>
|
||||
</div>
|
||||
<!-- / Layout wrapper -->
|
||||
|
||||
<!-- div class="buy-now">
|
||||
<a
|
||||
href="https://themeselection.com/products/sneat-bootstrap-html-admin-template/"
|
||||
target="_blank"
|
||||
class="btn btn-danger btn-buy-now"
|
||||
>Upgrade to Pro</a
|
||||
>
|
||||
</div -->
|
||||
|
||||
<!-- Page JS -->
|
||||
|
||||
<!-- Place this tag in your head or just before your close body tag. -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||