Implement Auth0, + templates.
This commit is contained in:
@@ -7,9 +7,14 @@ services:
|
||||
- "80"
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=Printbase;User Id=sa;Password=YourStrong(!)Password;Encrypt=false;TrustServerCertificate=true;MultipleActiveResultSets=true;
|
||||
- ConnectionStrings__DefaultConnection=Server=${SQL_SERVER};Database=${SQL_DATABASE};User Id=${SQL_USER_ID};Password=${SQL_PASSWORD};Encrypt=false;TrustServerCertificate=true;MultipleActiveResultSets=true;
|
||||
- ASPNETCORE_URLS=http://+:8080
|
||||
- Auth0__Domain=${AUTH0_ISSUER_BASE_URL}
|
||||
- Auth0__Audience=${AUTH0_AUDIENCE}
|
||||
depends_on:
|
||||
- mssql
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
webui:
|
||||
image: node:18-alpine
|
||||
@@ -20,7 +25,19 @@ services:
|
||||
- "3000"
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- AUTH0_SECRET=${AUTH0_SECRET}
|
||||
- APP_BASE_URL=${APP_BASE_URL}
|
||||
- AUTH0_DOMAIN=${AUTH0_ISSUER_BASE_URL}
|
||||
- AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
|
||||
- AUTH0_CLIENT_SECRET=${AUTH0_CLIENT_SECRET}
|
||||
- AUTH0_AUDIENCE=${AUTH0_AUDIENCE}
|
||||
- AUTH0_SCOPE=openid profile email read:shows
|
||||
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||
- NEXT_PUBLIC_AUTH0_CLIENT_ID=${NEXT_PUBLIC_AUTH0_CLIENT_ID}
|
||||
- NEXT_PUBLIC_AUTH0_DOMAIN=${NEXT_PUBLIC_AUTH0_DOMAIN}
|
||||
command: "sh -c 'npm install && npm run dev'"
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:2022-latest
|
||||
@@ -28,16 +45,27 @@ services:
|
||||
ports:
|
||||
- "1433:1433"
|
||||
environment:
|
||||
SA_PASSWORD: "YourStrong(!)Password"
|
||||
SA_PASSWORD: "${SQL_PASSWORD}"
|
||||
ACCEPT_EULA: "Y"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./ssl/impr.ink-chain.pem:/etc/ssl/certs/impr.ink.crt:ro
|
||||
- ./ssl/impr.ink-key.pem:/etc/ssl/private/impr.ink.key:ro
|
||||
depends_on:
|
||||
- webapi
|
||||
- webui
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
@@ -1,6 +1,14 @@
|
||||
events {}
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
proxy_buffer_size 16k;
|
||||
proxy_buffers 4 16k;
|
||||
proxy_busy_buffers_size 16k;
|
||||
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
upstream webapi {
|
||||
server webapi:8080;
|
||||
}
|
||||
@@ -11,6 +19,24 @@ http {
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name impr.ink;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name impr.ink;
|
||||
|
||||
ssl_certificate /etc/ssl/certs/impr.ink.crt;
|
||||
ssl_certificate_key /etc/ssl/private/impr.ink.key;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options DENY always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://webapi/;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using System.Security.Claims;
|
||||
using Imprink.Application;
|
||||
using Imprink.Application.Products.Handlers;
|
||||
using Imprink.Domain.Repositories;
|
||||
using Imprink.Infrastructure;
|
||||
using Imprink.Infrastructure.Database;
|
||||
using Imprink.Infrastructure.Repositories;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Imprink.WebApi;
|
||||
|
||||
@@ -29,6 +32,19 @@ public static class Startup
|
||||
cfg.RegisterServicesFromAssembly(typeof(CreateProductHandler).Assembly);
|
||||
});
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.Authority = $"https://{builder.Configuration["Auth0:Domain"]}/";
|
||||
options.Audience = builder.Configuration["Auth0:Audience"];
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
NameClaimType = ClaimTypes.NameIdentifier
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
services.AddControllers();
|
||||
services.AddSwaggerGen();
|
||||
}
|
||||
|
||||
759
webui/auth0-templates/login.html
Normal file
759
webui/auth0-templates/login.html
Normal file
@@ -0,0 +1,759 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<link rel="icon" href="https://i.ibb.co/gbthcbnP/logo-sm.png" type="image/png" />
|
||||
<title>Sign In | Imprink</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link href="https://fonts.cdnfonts.com/css/scanno-hanley-pro-sans" rel="stylesheet">
|
||||
</head>
|
||||
<style>
|
||||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f9f9f9;
|
||||
background-image: url('https://i.ibb.co/BDSg5pD/vecteezy-abstract-arrows-ribbons-crowns-hearts-explosions-and-5891677.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
backdrop-filter: blur(8px);
|
||||
background: linear-gradient(135deg,
|
||||
rgba(108, 92, 231, 0.4),
|
||||
rgba(0, 184, 148, 0.4)
|
||||
);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 0 5%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
gap: clamp(20px, 5vw, 150px);
|
||||
}
|
||||
|
||||
.logo-section {
|
||||
flex: 0 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: slideLeft 1s ease-out;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.logo-section img {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.login-section {
|
||||
flex: 0 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: slideRight 1s ease-out;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.login-box {
|
||||
padding: 20px;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1),
|
||||
0 2px 8px rgba(0, 0, 0, 0.05),
|
||||
inset 0 1px 1px rgba(255, 255, 255, 0.1),
|
||||
0 0 20px rgba(108, 92, 231, 0.2),
|
||||
0 0 40px rgba(0, 184, 148, 0.1);
|
||||
border-radius: 20px;
|
||||
width: 90%;
|
||||
max-width: 400px;
|
||||
min-width: 360px;
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.login-header h3 {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
font-size: 28px;
|
||||
color: #2d3436;
|
||||
margin: 15px 0 5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.login-header h5 {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
font-size: 14px;
|
||||
color: #636e72;
|
||||
font-weight: 500;
|
||||
letter-spacing: 1px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.login-header img {
|
||||
width: 80%;
|
||||
animation: slideIn 0.8s ease-out forwards;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.login-header .mobile-logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#error-message {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
display: none;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
|
||||
#success-message {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
display: none;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
|
||||
.social-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.divider {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin: 25px 0;
|
||||
color: #636e72;
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.divider::before,
|
||||
.divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.divider::before {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.divider::after {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.social-btn {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #e0e0e0;
|
||||
background: white;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.social-btn img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.social-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.btn-google:hover {
|
||||
background: #DB4437;
|
||||
border-color: #DB4437;
|
||||
}
|
||||
|
||||
.btn-github:hover {
|
||||
background: #333;
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.btn-facebook:hover {
|
||||
background: #4267B2;
|
||||
border-color: #4267B2;
|
||||
}
|
||||
|
||||
.btn-linkedin:hover {
|
||||
background: #0077B5;
|
||||
border-color: #0077B5;
|
||||
}
|
||||
|
||||
.btn-windows:hover {
|
||||
background: #00A4EF;
|
||||
border-color: #00A4EF;
|
||||
}
|
||||
|
||||
#link-signup-login {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
cursor: pointer;
|
||||
color: #6c5ce7;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
#link-signup-login:hover {
|
||||
color: #5f4dd0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#btn-signup {
|
||||
background-color: #00b894;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#btn-signup:hover {
|
||||
background-color: #00a884;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0, 184, 148, 0.2);
|
||||
}
|
||||
|
||||
.form-control {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
max-width: 100%;
|
||||
padding: 16px;
|
||||
height: 40px;
|
||||
border: 1.5px solid rgba(0, 0, 0, 0.08);
|
||||
border-radius: 12px;
|
||||
transition: all 0.2s ease;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
background-color: #fff;
|
||||
color: #2d3436;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #6c5ce7;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.1);
|
||||
}
|
||||
|
||||
.form-control::placeholder {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
color: #b2bec3;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
color: #2d3436;
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
padding: 14px 16px;
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 14px;
|
||||
height: auto;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #6c5ce7;
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #5f4dd0;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(108, 92, 231, 0.2);
|
||||
}
|
||||
|
||||
@keyframes slideLeft {
|
||||
0% {
|
||||
transform: translateX(50%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideRight {
|
||||
0% {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.login-container {
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-section {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.login-section {
|
||||
width: 100%;
|
||||
animation: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-box {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
animation: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.login-header .mobile-logo {
|
||||
display: block;
|
||||
width: 80%;
|
||||
margin: 0 auto 20px auto;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(50px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.forgot-password {
|
||||
text-align: right;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.forgot-password a {
|
||||
font-family: 'Scanno Hanley Pro Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
color: #6c5ce7;
|
||||
font-size: 13px;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.forgot-password a:hover {
|
||||
color: #5f4dd0;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="login-container">
|
||||
<div class="logo-section">
|
||||
<img src="https://i.ibb.co/0RK5CM5Q/logo-light.png" class="img-fluid"/>
|
||||
</div>
|
||||
<div class="login-section">
|
||||
<div class="login-box">
|
||||
<div class="login-header">
|
||||
<img src="https://i.ibb.co/0RK5CM5Q/logo-light.png" class="img-fluid mobile-logo"/>
|
||||
<h3>Welcome</h3>
|
||||
<h5>PLEASE LOG IN</h5>
|
||||
</div>
|
||||
<div id="error-message" class="alert alert-danger"></div>
|
||||
<div id="success-message" class="alert alert-success"></div>
|
||||
<form onsubmit="return false;" method="post">
|
||||
<div class="form-group">
|
||||
<label for="name">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
id="email"
|
||||
placeholder="Enter your email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Password</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
id="password"
|
||||
placeholder="Enter your password">
|
||||
<div class="forgot-password">
|
||||
<a href="#" id="forgot-password-link">Forgot your password?</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="captcha-container form-group"></div>
|
||||
<button
|
||||
type="submit"
|
||||
id="btn-login"
|
||||
class="btn btn-primary btn-block">
|
||||
Log In
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="btn-signup"
|
||||
class="btn btn-default btn-block invisible">
|
||||
Sign Up
|
||||
</button>
|
||||
<div class="divider" id="divider">or continue with</div>
|
||||
<div class="social-buttons" id="social-buttons">
|
||||
<button
|
||||
type="button"
|
||||
id="btn-google"
|
||||
class="social-btn btn-google"
|
||||
title="Sign in with Google">
|
||||
<img src="https://cdn4.iconfinder.com/data/icons/logos-brands-7/512/google_logo-google_icongoogle-512.png" alt="Google">
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="btn-github"
|
||||
class="social-btn btn-github"
|
||||
title="Sign in with GitHub">
|
||||
<img src="https://img.icons8.com/m_outlined/512/github.png" alt="GitHub">
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="btn-facebook"
|
||||
class="social-btn btn-facebook"
|
||||
title="Sign in with Facebook">
|
||||
<img src="https://www.freeiconspng.com/uploads/facebook-png-icon-follow-us-facebook-1.png" alt="Facebook">
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="btn-linkedin"
|
||||
class="social-btn btn-linkedin"
|
||||
title="Sign in with LinkedIn">
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/LinkedIn_icon.svg/1024px-LinkedIn_icon.svg.png" alt="LinkedIn">
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="btn-windows"
|
||||
class="social-btn btn-windows"
|
||||
title="Sign in with Microsoft">
|
||||
<img src="https://cdn-icons-png.freepik.com/256/11378/11378754.png?semt=ais_hybrid" alt="Microsoft">
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<span id="login-signup-msg">Don't have an account?</span> <a id="link-signup-login"> Sign Up </a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--[if IE 8]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!--[if lte IE 9]>
|
||||
<script src="https://cdn.auth0.com/js/polyfills/1.0/base64.min.js"></script>
|
||||
<script src="https://cdn.auth0.com/js/polyfills/1.0/es5-shim.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="https://cdn.auth0.com/js/auth0/9.28/auth0.min.js"></script>
|
||||
<script src="https://cdn.auth0.com/js/polyfills/1.0/object-assign.min.js"></script>
|
||||
<script>
|
||||
function capitalizeFirstLetter(str) {
|
||||
if (!str) return '';
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
|
||||
var config = JSON.parse(
|
||||
decodeURIComponent(escape(window.atob('@@config@@')))
|
||||
);
|
||||
|
||||
var leeway = config.internalOptions.leeway;
|
||||
if (leeway) {
|
||||
var convertedLeeway = parseInt(leeway);
|
||||
|
||||
if (!isNaN(convertedLeeway)) {
|
||||
config.internalOptions.leeway = convertedLeeway;
|
||||
}
|
||||
}
|
||||
|
||||
var params = {
|
||||
overrides: {
|
||||
__tenant: config.auth0Tenant,
|
||||
__token_issuer: config.authorizationServer.issuer
|
||||
},
|
||||
domain: config.auth0Domain,
|
||||
clientID: config.clientID,
|
||||
redirectUri: config.callbackURL,
|
||||
responseType: 'code',
|
||||
scope: config.internalOptions.scope,
|
||||
_csrf: config.internalOptions._csrf,
|
||||
state: config.internalOptions.state,
|
||||
_intstate: config.internalOptions._intstate
|
||||
};
|
||||
|
||||
var triggerCaptcha = null;
|
||||
var signupCaptcha = null;
|
||||
var webAuth = new auth0.WebAuth(params);
|
||||
var databaseConnection = 'Username-Password-Authentication';
|
||||
var captcha = webAuth.renderCaptcha(
|
||||
document.querySelector('.captcha-container'),
|
||||
null,
|
||||
(error, payload) => {
|
||||
if (payload) {
|
||||
triggerCaptcha = payload.triggerCaptcha;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function login(e) {
|
||||
e.preventDefault();
|
||||
var button = this;
|
||||
var username = document.getElementById('email').value;
|
||||
var password = document.getElementById('password').value;
|
||||
button.disabled = true;
|
||||
|
||||
var request = () => {
|
||||
webAuth.login({
|
||||
realm: databaseConnection,
|
||||
username: username,
|
||||
password: password,
|
||||
captcha: captcha.getValue()
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
button.disabled = false;
|
||||
});
|
||||
};
|
||||
|
||||
if (triggerCaptcha) {
|
||||
triggerCaptcha(request);
|
||||
} else {
|
||||
request();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSignupLogin(e) {
|
||||
e.preventDefault();
|
||||
var loginSignupLink = e.target;
|
||||
var loginBtn = document.getElementById('btn-login');
|
||||
var signupBtn = document.getElementById('btn-signup');
|
||||
var msg = document.getElementById('login-signup-msg');
|
||||
var socialButtons = document.getElementById('social-buttons');
|
||||
var divider = document.getElementById('divider');
|
||||
|
||||
loginBtn.classList.toggle('invisible');
|
||||
signupBtn.classList.toggle('invisible');
|
||||
socialButtons.classList.toggle('invisible');
|
||||
divider.classList.toggle('invisible');
|
||||
|
||||
if (signupBtn.classList.contains('invisible')) {
|
||||
loginSignupLink.innerHTML = "Sign Up";
|
||||
msg.innerHTML = "Don't have an account?";
|
||||
} else {
|
||||
loginSignupLink.innerHTML = "Log In";
|
||||
msg.innerHTML = "Already have an account?";
|
||||
}
|
||||
|
||||
if (signupBtn.classList.contains('invisible')) {
|
||||
captcha = webAuth.renderCaptcha(
|
||||
document.querySelector('.captcha-container'),
|
||||
null,
|
||||
(error, payload) => {
|
||||
if (payload) {
|
||||
triggerCaptcha = payload.triggerCaptcha;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
signupCaptcha = webAuth.renderSignupCaptcha(
|
||||
document.querySelector('.captcha-container'),
|
||||
null,
|
||||
(error, payload) => {
|
||||
if (payload) {
|
||||
triggerCaptcha = payload.triggerCaptcha;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function signup() {
|
||||
var button = this;
|
||||
var email = document.getElementById('email').value;
|
||||
var password = document.getElementById('password').value;
|
||||
button.disabled = true;
|
||||
|
||||
var request = () => {
|
||||
webAuth.redirect.signupAndLogin({
|
||||
connection: databaseConnection,
|
||||
email: email,
|
||||
password: password,
|
||||
captcha: signupCaptcha.getValue()
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
button.disabled = false;
|
||||
});
|
||||
};
|
||||
|
||||
if (triggerCaptcha) {
|
||||
triggerCaptcha(request);
|
||||
} else {
|
||||
request();
|
||||
}
|
||||
}
|
||||
|
||||
function loginWithGoogle() {
|
||||
webAuth.authorize({
|
||||
connection: 'google-oauth2'
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
});
|
||||
}
|
||||
|
||||
function loginWithGithub() {
|
||||
webAuth.authorize({
|
||||
connection: 'github'
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
});
|
||||
}
|
||||
|
||||
function loginWithFacebook() {
|
||||
webAuth.authorize({
|
||||
connection: 'facebook'
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
});
|
||||
}
|
||||
|
||||
function loginWithLinkedIn() {
|
||||
webAuth.authorize({
|
||||
connection: 'linkedin'
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
});
|
||||
}
|
||||
|
||||
function loginWithWindows() {
|
||||
webAuth.authorize({
|
||||
connection: 'windowslive'
|
||||
}, function(err) {
|
||||
if (err) displayError(err);
|
||||
});
|
||||
}
|
||||
|
||||
function displayError(err) {
|
||||
captcha.reload();
|
||||
var successMessage = document.getElementById('success-message');
|
||||
successMessage.style.display = 'none';
|
||||
var errorMessage = document.getElementById('error-message');
|
||||
errorMessage.innerText = capitalizeFirstLetter(err.policy) || capitalizeFirstLetter(err.description);
|
||||
errorMessage.style.display = 'block';
|
||||
}
|
||||
|
||||
function displaySuccess(text) {
|
||||
captcha.reload();
|
||||
var errorMessage = document.getElementById('error-message');
|
||||
errorMessage.style.display = 'none';
|
||||
var successMessage = document.getElementById('success-message');
|
||||
successMessage.innerText = text;
|
||||
successMessage.style.display = 'block';
|
||||
}
|
||||
|
||||
function forgotPassword(e) {
|
||||
e.preventDefault();
|
||||
try {
|
||||
var config = JSON.parse(
|
||||
decodeURIComponent(escape(window.atob('@@config@@')))
|
||||
);
|
||||
|
||||
webAuth.changePassword({
|
||||
connection: databaseConnection,
|
||||
email: document.getElementById('email').value
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
console.error('Error:', err);
|
||||
displayError(err);
|
||||
} else {
|
||||
displaySuccess('Password reset email sent! Please check your inbox.');
|
||||
console.log('Password reset email sent');
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in forgot password:', error);
|
||||
displayError({ description: 'Unable to process password reset request. Please try again.' });
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('btn-login').addEventListener('click', login);
|
||||
document.getElementById('btn-google').addEventListener('click', loginWithGoogle);
|
||||
document.getElementById('btn-github').addEventListener('click', loginWithGithub);
|
||||
document.getElementById('btn-facebook').addEventListener('click', loginWithFacebook);
|
||||
document.getElementById('btn-linkedin').addEventListener('click', loginWithLinkedIn);
|
||||
document.getElementById('btn-windows').addEventListener('click', loginWithWindows);
|
||||
document.getElementById('btn-signup').addEventListener('click', signup);
|
||||
document.getElementById('link-signup-login').addEventListener('click', toggleSignupLogin);
|
||||
document.getElementById('forgot-password-link').addEventListener('click', forgotPassword);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
86
webui/package-lock.json
generated
86
webui/package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "webui",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@auth0/nextjs-auth0": "^4.6.0",
|
||||
"next": "15.3.3",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
@@ -44,6 +45,33 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@auth0/nextjs-auth0": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@auth0/nextjs-auth0/-/nextjs-auth0-4.6.0.tgz",
|
||||
"integrity": "sha512-HK+fcUW6P8/qUDQfOfntftMg6yzeZLtyfTxL/lyeOub1o/xTL9SZ2fF39nH0H6w1loB5SCAbyN1vD8xxBwINqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@edge-runtime/cookies": "^5.0.1",
|
||||
"@panva/hkdf": "^1.2.1",
|
||||
"jose": "^5.9.6",
|
||||
"oauth4webapi": "^3.1.2",
|
||||
"swr": "^2.2.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^14.2.25 || ^15.2.3",
|
||||
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edge-runtime/cookies": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@edge-runtime/cookies/-/cookies-5.0.2.tgz",
|
||||
"integrity": "sha512-Sd8LcWpZk/SWEeKGE8LT6gMm5MGfX/wm+GPnh1eBEtCpya3vYqn37wYknwAHw92ONoyyREl1hJwxV/Qx2DWNOg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz",
|
||||
@@ -650,6 +678,15 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@panva/hkdf": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
||||
"integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
@@ -1033,6 +1070,15 @@
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||
@@ -1081,6 +1127,15 @@
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
|
||||
"integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.30.1",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||
@@ -1469,6 +1524,15 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/oauth4webapi": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.5.1.tgz",
|
||||
"integrity": "sha512-txg/jZQwcbaF7PMJgY7aoxc9QuCxHVFMiEkDIJ60DwDz3PbtXPQnrzo+3X4IRYGChIwWLabRBRpf1k9hO9+xrQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@@ -1636,6 +1700,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/swr": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-2.3.3.tgz",
|
||||
"integrity": "sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3",
|
||||
"use-sync-external-store": "^1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz",
|
||||
@@ -1677,6 +1754,15 @@
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
|
||||
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth0/nextjs-auth0": "^4.6.0",
|
||||
"next": "15.3.3",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"next": "15.3.3"
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
|
||||
@@ -3,101 +3,7 @@ import Image from "next/image";
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
||||
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
|
||||
<li className="mb-2 tracking-[-.01em]">
|
||||
Get started by editing{" "}
|
||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-[family-name:var(--font-geist-mono)] font-semibold">
|
||||
src/app/page.js
|
||||
</code>
|
||||
.
|
||||
</li>
|
||||
<li className="tracking-[-.01em]">
|
||||
Save and see your changes instantly.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</footer>
|
||||
<a href="/auth/login">Login</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
8
webui/src/lib/auth0.js
Normal file
8
webui/src/lib/auth0.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Auth0Client } from "@auth0/nextjs-auth0/server";
|
||||
|
||||
export const auth0 = new Auth0Client({
|
||||
authorizationParameters: {
|
||||
scope: 'openid profile email read:shows',
|
||||
audience: 'imprink-front'
|
||||
}
|
||||
});
|
||||
11
webui/src/middleware.js
Normal file
11
webui/src/middleware.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { auth0 } from "./lib/auth0";
|
||||
|
||||
export async function middleware(request) {
|
||||
return await auth0.middleware(request);
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user