Commit 84f3bb29 authored by Josh Ji's avatar Josh Ji

init commit

parents
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
FROM openjdk:11
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT java -jar app.jar
\ No newline at end of file
This diff is collapsed.
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a fidoUser defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>RPServer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>RPServer</name>
<description>RPServer</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<!-- https://mvnrepository.com/artifact/com.webauthn4j/webauthn4j-core -->
<groupId>com.webauthn4j</groupId>
<artifactId>webauthn4j-core</artifactId>
<version>0.20.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.example.rpserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RpServerApplication {
public static void main(String[] args) {
SpringApplication.run(RpServerApplication.class, args);
}
}
package com.example.rpserver.controller;
import com.example.rpserver.model.Credential;
import com.example.rpserver.model.Response;
import com.example.rpserver.repository.CredentialRepository;
import com.webauthn4j.data.PublicKeyCredentialDescriptor;
import com.webauthn4j.data.PublicKeyCredentialRequestOptions;
import com.webauthn4j.data.PublicKeyCredentialType;
import com.webauthn4j.data.client.challenge.Challenge;
import com.webauthn4j.data.client.challenge.DefaultChallenge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;
import java.util.List;
@RestController
public class GetAssertion {
private static Logger logger = LoggerFactory.getLogger(GetAssertion.class);
@Autowired
private CredentialRepository credentialRepository;
@ResponseBody
@PostMapping("/BeginGetAssertion")
public ResponseEntity<PublicKeyCredentialRequestOptions> beginGetAssertion(@RequestParam("username") String username){
Challenge challenge = new DefaultChallenge();
List<Credential> credentials = credentialRepository.getCredentialsByUserName(username);
LinkedList<PublicKeyCredentialDescriptor> publicKeyCredentialDescriptors = new LinkedList<>();
for(Credential credential : credentials){
PublicKeyCredentialDescriptor publicKeyCredentialDescriptor = new PublicKeyCredentialDescriptor(PublicKeyCredentialType.PUBLIC_KEY, credential.getRawId(), null);
publicKeyCredentialDescriptors.add(publicKeyCredentialDescriptor);
}
PublicKeyCredentialRequestOptions options = new PublicKeyCredentialRequestOptions(challenge, null, "localhost", publicKeyCredentialDescriptors, null, null);
return ResponseEntity.ok(options);
}
@ResponseBody
@PostMapping("/FinishGetAssertion")
public ResponseEntity<Response> finishMakeCredential(@RequestParam("data") String data){
logger.info("data : {}", data);
logger.info("Finish Get Assertion");
return ResponseEntity.ok(new Response(true, "Login Successfully"));
}
}
package com.example.rpserver.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class Home {
@GetMapping("/")
public String home(){
return "index.html";
}
}
package com.example.rpserver.controller;
import com.example.rpserver.model.Credential;
import com.example.rpserver.model.FidoUser;
import com.example.rpserver.model.Response;
import com.example.rpserver.repository.CredentialRepository;
import com.example.rpserver.repository.UserRepository;
import com.webauthn4j.WebAuthnManager;
import com.webauthn4j.data.*;
import com.webauthn4j.data.attestation.statement.COSEAlgorithmIdentifier;
import com.webauthn4j.data.client.challenge.Challenge;
import com.webauthn4j.data.client.challenge.DefaultChallenge;
import com.webauthn4j.util.Base64Util;
import com.webauthn4j.util.HexUtil;
import com.webauthn4j.validator.attestation.statement.AttestationStatementValidator;
import com.webauthn4j.validator.attestation.trustworthiness.certpath.NullCertPathTrustworthinessValidator;
import com.webauthn4j.validator.attestation.trustworthiness.self.NullSelfAttestationTrustworthinessValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.SecureRandom;
import java.util.Date;
import java.util.LinkedList;
@RestController
public class MakeCredential {
private final Logger logger = LoggerFactory.getLogger(MakeCredential.class);
private final SecureRandom secureRandom = new SecureRandom();
@Autowired
private UserRepository userRepository;
@Autowired
private CredentialRepository credentialRepository;
@ResponseBody
@PostMapping("/BeginMakeCredential")
public ResponseEntity<PublicKeyCredentialCreationOptions> beginMakeCredential(@RequestParam("username") String username,
@RequestParam("advanced") String advanced,
@RequestParam("advancedOptions") String advancedOptions,
@RequestHeader(HttpHeaders.HOST) String host){
byte[] userIdBytes = new byte[32];
secureRandom.nextBytes(userIdBytes);
PublicKeyCredentialUserEntity userEntity = new PublicKeyCredentialUserEntity(userIdBytes, username, username);
PublicKeyCredentialRpEntity rp = new PublicKeyCredentialRpEntity("localhost", "localhost");
Challenge challenge = new DefaultChallenge();
LinkedList<PublicKeyCredentialParameters> parameters = new LinkedList<>();
parameters.add(new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS256));
parameters.add(new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256));
PublicKeyCredentialCreationOptions options = new PublicKeyCredentialCreationOptions(rp, userEntity, challenge, parameters);
FidoUser fidoUser = new FidoUser(userIdBytes, challenge.toString(), username);
userRepository.save(fidoUser);
return ResponseEntity.ok(options);
}
@ResponseBody
@PostMapping("/FinishMakeCredential")
public ResponseEntity<Response> finishMakeCredential(@RequestParam("identifier") String identifier,
@RequestParam("rawId") byte[] rawId,
@RequestParam("clientDataJSON") byte[] clientDataJSONBytes,
@RequestParam("attestationObject") byte[] attestationObjectBytes){
// apply base64 decoding
clientDataJSONBytes = Base64Util.decode(clientDataJSONBytes);
attestationObjectBytes = Base64Util.decode(attestationObjectBytes);
rawId = Base64Util.decode(rawId);
// logger
logger.info("clientDataJson : {}", new String(clientDataJSONBytes));
logger.info("attestationObject hex String : {}", HexUtil.encodeToString(attestationObjectBytes));
logger.info("rawId hex String : {}", HexUtil.encodeToString(rawId));
RegistrationRequest registrationRequest = new RegistrationRequest(attestationObjectBytes, clientDataJSONBytes);
LinkedList<AttestationStatementValidator> attestationStatementValidators = new LinkedList<>();
WebAuthnManager webAuthnManager = new WebAuthnManager(attestationStatementValidators, new NullCertPathTrustworthinessValidator(), new NullSelfAttestationTrustworthinessValidator());
RegistrationData registrationData = webAuthnManager.parse(registrationRequest);
logger.info(registrationData.toString());
FidoUser user = userRepository.findByChallenge(registrationData.getCollectedClientData().getChallenge().toString());
credentialRepository.save(new Credential(
new Date(),
registrationData.getAttestationObject().getAuthenticatorData().getSignCount(),
identifier,
null,
user.getUserName(),
rawId));
return ResponseEntity.ok().body(new Response(true, "Successfully created credential"));
}
}
package com.example.rpserver.controller;
import com.example.rpserver.model.Credential;
import com.example.rpserver.model.CredentialItem;
import com.example.rpserver.repository.CredentialRepository;
import com.google.gson.JsonArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;
import java.util.List;
@RestController
public class RegisteredKeys {
@Autowired
CredentialRepository credentialRepository;
@ResponseBody
@PostMapping("/RegisteredKeys")
public ResponseEntity<List<CredentialItem>> registeredKeys(){
List<Credential> list = credentialRepository.getAllByIdIsNotNull();
LinkedList<CredentialItem> items = new LinkedList<>();
for(Credential credential : list){
CredentialItem item = new CredentialItem();
item.handle = credential.getIdentifier();
item.base64handle = credential.getIdentifier();
item.userVerificationMethod = credential.getUvMethod();
item.date = credential.getDate().toString();
items.add(item);
}
return ResponseEntity.ok(items);
}
}
package com.example.rpserver.model;
import com.webauthn4j.data.PublicKeyCredentialEntity;
import javax.persistence.*;
import java.util.Date;
@Entity
public class Credential {
public Credential(Date date, long signCount, String identifier, String uvMethod, String userName, byte[] rawId) {
this.date = date;
this.signCount = signCount;
this.identifier = identifier;
this.uvMethod = uvMethod;
this.userName = userName;
this.rawId = rawId;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public Credential() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "date")
private Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Column(name = "sign_count", nullable = false)
private long signCount;
public long getSignCount() {
return signCount;
}
public void setSignCount(int signCount) {
this.signCount = signCount;
}
@Column(name = "identifier")
private String identifier;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String credential) {
this.identifier = credential;
}
@Column(name = "uv_method")
private String uvMethod;
public String getUvMethod() {
return uvMethod;
}
public void setUvMethod(String uvMethod) {
this.uvMethod = uvMethod;
}
@Column(name = "user_name")
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Lob
@Column(name = "raw_id")
private byte[] rawId;
public byte[] getRawId() {
return rawId;
}
public void setRawId(byte[] rawId) {
this.rawId = rawId;
}
}
package com.example.rpserver.model;
import java.util.List;
public class CredentialItem {
public String base64handle;
public String date;
public String handle;
public String hasCable;
public String id;
public String name;
public String publicKey;
public List<String> transports;
public String userVerificationMethod;
}
package com.example.rpserver.model;
import javax.persistence.*;
@Entity
@Table
public class FidoUser {
protected FidoUser(){}
public FidoUser(byte[] rawId, String challenge, String userName){
this.rawId = rawId;
this.challenge = challenge;
this.userName = userName;
}
@Column(name = "user_name")
private String userName;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "challenge", nullable = true)
private String challenge;
public String getChallenge() {
return challenge;
}
public void setChallenge(String challenge) {
this.challenge = challenge;
}
@Column(name = "raw_id")
private byte[] rawId;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public byte[] getRawId() {
return rawId;
}
public void setRawId(byte[] rawId) {
this.rawId = rawId;
}
}
package com.example.rpserver.model;
public class Response {
private boolean success;
private String message;
public Response(boolean success, String message){
this.success = success;
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.example.rpserver.repository;
import com.example.rpserver.model.Credential;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CredentialRepository extends JpaRepository<Credential, Long> {
List<Credential> getAllByIdIsNotNull();
List<Credential> getCredentialsByUserName(String username);
}
package com.example.rpserver.repository;
import com.example.rpserver.model.FidoUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<FidoUser, Long> {
public FidoUser findByChallenge(String challenge);
}
\ No newline at end of file
server:
address: 0.0.0.0
port: 8080
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix:
encoding: UTF-8
mode: HTML
web:
resources:
static-locations: classpath:/static/
cache:
cache control:
no-cache: true
h2:
console:
enabled: true
path: /h2
datasource:
url: jdbc:h2:mem:RPdb
username: sa
password: password
driver-class-name: org.h2.Driver
sql:
init:
mode: always
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
\ No newline at end of file
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.flex-layout {
display: flex;
height: 100%;
flex-direction: column;
}
.mdl-snackbar {
line-height: 1;
}
.flex-content {
flex: 1 1 auto;
}
.mdl-mini-footer {
padding-top: 3px;
padding-bottom: 3px;
}
#header-buttons {
padding: 0 16px;
flex-wrap: wrap;
min-height: 56px;
height: auto;
}
#header-buttons > button {
flex: 1 1 auto;
margin-bottom: 8px;
}
#header-buttons > .mdl-textfield {
flex: 1 1 auto;
margin-bottom: 8px;
}
#username-input{
min-width: 64px;
width: 100%;
margin-right: 12px;
margin-left: 12px;
}
.fingerprint {
width: 36px;
height: 36px;
background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M17.81%204.47c-.08%200-.16-.02-.23-.06C15.66%203.42%2014%203%2012.01%203c-1.98%200-3.86.47-5.57%201.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82%202.52%209.86%202%2012.01%202c2.13%200%203.99.47%206.03%201.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5%209.72c-.1%200-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4%202.25-2.5%203.75-3.27C9.98%204.04%2014%204.03%2017.15%205.65c1.5.77%202.76%201.86%203.75%203.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5%201.7-3.4%202.96-.08.14-.23.21-.39.21zm6.25%2012.07c-.13%200-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34%200-2.97%202.54-5.39%205.66-5.39s5.66%202.42%205.66%205.39c0%20.28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57%200-4.66%201.97-4.66%204.39%200%201.44.32%202.77.93%203.85.64%201.15%201.08%201.64%201.85%202.42.19.2.19.51%200%20.71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19%200-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39%200-.28.22-.5.5-.5s.5.22.5.5c0%201.41.72%202.74%201.94%203.56.71.48%201.54.71%202.54.71.24%200%20.64-.03%201.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91%2022c-.04%200-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22%200-1.62%201.38-2.94%203.08-2.94%201.7%200%203.08%201.32%203.08%202.94%200%201.07.93%201.94%202.08%201.94s2.08-.87%202.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84%200-5.44%201.58-6.61%204.03-.39.81-.59%201.76-.59%202.8%200%20.78.07%202.01.67%203.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96%200-1.2.23-2.29.68-3.24%201.33-2.79%204.28-4.6%207.51-4.6%204.55%200%208.25%203.51%208.25%207.83%200%201.62-1.38%202.94-3.08%202.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08%201.94c0%201.71.66%203.31%201.87%204.51.95.94%201.86%201.46%203.27%201.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z%22%20fill%3D%22white%22%2F%3E%3Cpath%20fill%3D%22none%22%20d%3D%22M0%200h24v24H0z%22%2F%3E%3C%2Fsvg%3E%20');
background-size: contain;
background-repeat: no-repeat;
cursor: pointer;
}
.mdl-layout__drawer .mdl-checkbox__label {
vertical-align: top;
}
.mdl-cell {
padding: 30px;
text-align: left;
}
.mdl-card__subtitle-text {
padding-left: .2cm;
font-weight: bold;
}
.mdl-card__supporting-text {
font-style: italic;
overflow-wrap: break-word;
word-wrap: break-word;
padding-bottom: 8px;
padding-top: 8px;
}
.mdl-switch {
width: auto;
}
.mdl-checkbox{
word-wrap:break-word;
word-break: keep-all;
height: auto;
}
.mdl-textfield__input{
padding: 5px;
}
.login-card.mdl-card {
width: 350px;
height: 350px;
margin-left: auto;
margin-right: auto;
margin-top: 20px;
}
.outer-next {
position: absolute;
text-align: right;
bottom: .5cm;
right: .5cm;
}
.login-card.mdl-card__title {
margin-bottom: 2cm;
}
.username-card {
position: relative;
display: block;
margin : 0 auto;
}
.boxes {
position: relative;
height: 50px;
}
.top-box {
position: absolute;
top: 5px;
}
.bottom-box {
position: absolute;
top: 5px;
}
.instructions {
height: 200px;
}
.auth-spinner {
position: relative;
display: block;
margin : 0 auto;
}
.mdl-spinner {
width: 84px;
height: 84px;
}
.mdl-spinner__circle {
border-width: 6px;
}
.signin-title {
height: 75px;
}
.instruction-text {
transition: opacity 0.8s;
}
.gone {
opacity: 0;
}
.next-button.mdl-button {
width: 100px;
}
.advanced-switch {
background-color: white;
padding-top: .2cm;
padding-bottom: .2cm;
padding-left: .2cm;
}
.advanced {
background-color: white;
padding-top: .2cm;
padding-bottom: .2cm;
padding-left: .2cm;
}
.attachment {
font-size: medium;
}
.auth-button {
margin-left: .25cm;
margin-right: .25cm;
}
.make-button {
margin-left: .25cm;
margin-right: .25cm;
}
.isuvpaa-button {
margin-left: .25cm;
margin-right: .25cm;
}
.logout-button {
margin-left: .25cm;
margin-right: .25cm;
color: white;
}
.hidden {
display: none;
}
.activity-bar {
padding-top: 0;
padding-bottom: .2cm;
margin: 0;
}
.page-width {
width: 100%;
}
.active-text {
margin: 0;
background-color: white;
text-align: center;
font-size: medium;
}
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet"
href="https://code.getmdl.io/1.3.0/material.teal-pink.min.css"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
<link href="css/webauthn.css" rel="stylesheet">
<script src="//code.getmdl.io/1.3.0/material.min.js"></script>
<!-- Web Animations polyfill for Edge. -->
<script src="https://rawgit.com/web-animations/web-animations-js/master/web-animations.min.js"></script>
<title>Relying Party Server</title>
</head>
<body>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<header class="mdl-layout__header">
<div class="mdl-layout__header-row">
<span class="mdl-layout__title">WebAuthn Demo</span>
</div>
<div id="header-buttons" class="mdl-layout__header-row">
<div id="username-input" class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" id="username"/>
<label class="mdl-textfield__label" for="username">Username</label>
</div>
<button id="credential-button"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect make-button"
title="Calls MakeCredential to register a new credential from a FIDO device"
>
Register
</button>
<button id="authenticate-button"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect auth-button"
title="Calls GetAssertion to request an assertion from a previously-registered FIDO device"
>
Login
</button>
</div>
</header>
<div class="mdl-layout__drawer">
<span class="mdl-layout-title">Advanced Options</span>
<div class="mdl-list">
<div class="mdl-list__item">
<label class="mdl-checkbox mdl-js-checkbox" for="switch-rr">
<input type="checkbox" id="switch-rr" class="mdl-checkbox__input">
<span class="mdl-checkbox__label">Prevent Reregistration</span>
</label>
</div>
<div class="mdl-list__item">
<label for="attachment" class="attachment">Attachment Type</label>
<select id="attachment" class="attachment">
<option value="none">N/A</option>
<option value="platform">Platform</option>
<option value="cross-platform">Cross-Platform</option>
</select>
</div>
<div class="mdl-list__item">
<label for="conveyance" class="attachment">Conveyance Preference</label>
<select id="conveyance" class="attachment">
<option value="NA">N/A</option>
<option value="none">None</option>
<option value="indirect">Indirect</option>
<option value="direct">Direct</option>
</select>
</div>
<div class="mdl-list__item">
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="switch-rk">
<input type="checkbox" id="switch-rk" class="mdl-checkbox__input">
<span class="mdl-checkbox__label">Require resident key</span>
</label>
</div>
<div class="mdl-list__item">
<label for="userVerification" class="attachment">User Verification</label>
<select id="userVerification" class="attachment">
<option value="none">None</option>
<option value="required">Required</option>
<option value="preferred">Preferred</option>
<option value="discouraged">Discouraged</option>
</select>
</div>
<div class="mdl-list__item">
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="switch-uvm">
<input type="checkbox" id="switch-uvm" class="mdl-checkbox__input">
<span class="mdl-checkbox__label">User Verification Method</span>
</label>
</div>
<div class="mdl-list__item">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" id="customTimeout">
<label class="mdl-textfield__label" for="customTimeout">Timeout (milliseconds)</label>
<span class="mdl-textfield__error">Input is not a number!</span>
</div>
</div>
<div class="mdl-list__item">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" id="abortTimeout">
<label class="mdl-textfield__label" for="abortTimeout">AbortTimeout (milliseconds)</label>
<span class="mdl-textfield__error">Input is not a number!</span>
</div>
</div>
</div>
</div>
<main class="flex-layout">
<div class="mdl-layout__content mdl-color--grey-100 flex-content">
<div id="active" class="hidden activity-bar">
<h3 class="active-text">Waiting for fidoUser touch</h3>
<div class="mdl-progress mdl-js-progress mdl-progress__indeterminate page-width"></div>
</div>
<div id="credentials" class="mdl-grid mdl-grid--no-spacing"></div>
</div>
<footer id="github" class="mdl-mini-footer">
<div class="mdl-mini-footer__left-section">
<ul class="mdl-mini-footer__link-list">
</ul>
</div>
<div class="mdl-mini-footer__right-section">
<ul class="mdl-mini-footer__link-list">
<li>
<a href="https://github.com/google/webauthndemo">GitHub</a>
</li>
</ul>
</div>
</footer>
<div id="snack-bar" class="mdl-js-snackbar mdl-snackbar">
<div class="mdl-snackbar__text"></div>
<button class="mdl-snackbar__action" type="button"></button>
</div>
</main>
</div>
<script src="js/webauthn.js"></script>
</body>
</html>
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Profile</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<!--navbar-->
<nav class="navbar bg-light navbar-light">
<div class="container-fluid">
<a href="#" class="navbar-brand">
<!-- <img src="img/logo1.png" alt="Taiwan Tech Logo" class="navbar-brand" style="height: 40pt">-->
FIDO DEMO
</a>
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#menu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="menu">
<ul class="navbar-nav">
<li class="nav-item">
<label for="switch-rk" class="nav-link">Resident Key</label>
<input type="checkbox" id="switch-rk">
</li>
<li class="nav-item">
<label for="switch-rr" class="nav-link">Prevent Registration</label>
<input type="checkbox" id="switch-rr">
</li>
<li class="nav-item">
<label for="switch-uvm" class="nav-link">User Verification Method</label>
<input type="checkbox" id="switch-uvm">
</li>
<li class="nav-item">
<label for="attachment" class="nav-link">Attachment Type</label>
<select id="attachment" class="attachment">
<option value="none">N/A</option>
<option value="cross-platform">Cross-Platform</option>
<option value="platform">Platform</option>
</select>
</li>
<li class="nav-item">
<label for="userVerification" class="nav-link">User Verification</label>
<select id="userVerification" class="attachment">
<option value="none">None</option>
<option value="required">Required</option>
<option value="preferred">Preferred</option>
<option value="discouraged">Discouraged</option>
</select>
</li>
<li class="nav-item">
<label for="conveyance" class="nav-link">Conveyance Preference</label>
<select id="conveyance" class="attachment">
<option value="NA">N/A</option>
<option value="none">None</option>
<option value="indirect">Indirect</option>
<option value="direct">Direct</option>
</select>
</li>
<li class="nav-item">
<label class="nav-link" for="customTimeout">Timeout (milliseconds)</label>
<input type="number" id="customTimeout">
</li>
<li class="nav-item">
<label class="nav-link" for="abortTimeout">AbortTimeout (milliseconds)</label>
<input type="number" id="abortTimeout">
</li>
</ul>
</div>
</div>
</nav>
<!-- body-->
<div class="container">
<div class="row justify-content-center">
<div class="col-4" style="width: 400px; padding-top: 150px;">
<div class="card shadow-lg p-5" style="border: 0px;">
<div class="row justify-content-start">
<h2>
Welcome!
</h2>
<hr>
<img src="img/avatar1.jpg" alt="Avatar1">
<h3 class="p-3">Name: Josh Ji</h3>
</div>
</div>
</div>
</div>
</div>
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
crossorigin="anonymous"></script>
</body>
</html>
\ No newline at end of file
package com.example.rpserver;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class RpServerApplicationTests {
@Test
void contextLoads() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment