[FEATURE] Add API docs and swagger-ui (#1544)
* [FEATURE] Add API docs and swagger-ui This change will serve out swagger-ui at the `/api/` root path. * Update descriptions and summaries in API spec * Utilise frontend assets from unit testing for Docker build steps * Fix tag for /api/user/* endpoints * Fix response schema for /api/user/info/2fa_method * Template and inject the session name during runtime into swagger-ui This change also factorises and renames index.go into template.go, this can now be generically utilised to template any file. * Fix integration tests * Add U2F endpoints * Change swagger directory to api This change is to more closely conform to the golang-standards project layout. * Add authentication for u2f endpoints * Modify u2f endpoint descriptions * Rename and fix u2f 2fa sign endpoints * Fix request body for /api/secondfactor/u2f/sign endpoint Co-authored-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/1557/head^2
parent
689fd7cb95
commit
3487fd392e
|
@ -14,6 +14,12 @@ if [[ $BUILDKITE_LABEL =~ ":selenium:" ]]; then
|
|||
docker tag authelia/authelia authelia:dist
|
||||
fi
|
||||
|
||||
if [[ $BUILDKITE_LABEL =~ ":docker: Build Image" ]] && [[ "${ARCH}" != "coverage" ]]; then
|
||||
echo "--- :react: :swagger: Extract frontend assets"
|
||||
buildkite-agent artifact download "authelia-public_html.tar.gz" .
|
||||
tar xzf authelia-public_html.tar.gz
|
||||
fi
|
||||
|
||||
if [[ $BUILDKITE_LABEL =~ ":docker: Deploy Image" ]]; then
|
||||
buildkite-agent artifact download "authelia-image-${ARCH}*" .
|
||||
zstdcat authelia-image-"${ARCH}".tar.zst | docker load
|
||||
|
|
|
@ -37,6 +37,7 @@ steps:
|
|||
artifact_paths:
|
||||
- "authelia-public_html.tar.gz"
|
||||
- "authelia-public_html.tar.gz.sha256"
|
||||
key: "unit-test"
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- wait:
|
||||
|
|
|
@ -17,6 +17,8 @@ if [[ "${BUILD_ARCH}" != "coverage" ]]; then
|
|||
cat << EOF
|
||||
- "authelia-${BUILD_OS}-${BUILD_ARCH}.tar.gz"
|
||||
- "authelia-${BUILD_OS}-${BUILD_ARCH}.tar.gz.sha256"
|
||||
depends_on:
|
||||
- "unit-test"
|
||||
EOF
|
||||
fi
|
||||
cat << EOF
|
||||
|
|
13
Dockerfile
13
Dockerfile
|
@ -1,14 +1,3 @@
|
|||
# ========================================
|
||||
# ===== Build image for the frontend =====
|
||||
# ========================================
|
||||
FROM node:15-alpine AS builder-frontend
|
||||
|
||||
WORKDIR /node/src/app
|
||||
COPY web .
|
||||
|
||||
# Install the dependencies and build
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn build
|
||||
|
||||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
|
@ -23,12 +12,12 @@ RUN apk --no-cache add gcc musl-dev
|
|||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod go.sum config.template.yml ./
|
||||
COPY --from=builder-frontend /node/src/app/build public_html
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY cmd cmd
|
||||
COPY internal internal
|
||||
COPY public_html public_html
|
||||
|
||||
# Prepare static files to be embedded in Go binary
|
||||
RUN go get -u aletheia.icu/broccoli && \
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
# ========================================
|
||||
# ===== Build image for the frontend =====
|
||||
# ========================================
|
||||
FROM node:15-alpine AS builder-frontend
|
||||
|
||||
WORKDIR /node/src/app
|
||||
COPY web .
|
||||
|
||||
# Install the dependencies and build
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn build
|
||||
|
||||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
|
@ -26,12 +15,12 @@ RUN apk --no-cache add curl && \
|
|||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod go.sum config.template.yml ./
|
||||
COPY --from=builder-frontend /node/src/app/build public_html
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY cmd cmd
|
||||
COPY internal internal
|
||||
COPY public_html public_html
|
||||
|
||||
# Prepare static files to be embedded in Go binary
|
||||
RUN go get -u aletheia.icu/broccoli && \
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
# ========================================
|
||||
# ===== Build image for the frontend =====
|
||||
# ========================================
|
||||
FROM node:15-alpine AS builder-frontend
|
||||
|
||||
WORKDIR /node/src/app
|
||||
COPY web .
|
||||
|
||||
# Install the dependencies and build
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn build
|
||||
|
||||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
|
@ -26,12 +15,12 @@ RUN apk --no-cache add curl && \
|
|||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod go.sum config.template.yml ./
|
||||
COPY --from=builder-frontend /node/src/app/build public_html
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY cmd cmd
|
||||
COPY internal internal
|
||||
COPY public_html public_html
|
||||
|
||||
# Prepare static files to be embedded in Go binary
|
||||
RUN go get -u aletheia.icu/broccoli && \
|
||||
|
|
|
@ -7,7 +7,8 @@ WORKDIR /node/src/app
|
|||
COPY web .
|
||||
|
||||
# Install the dependencies and build
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn coverage
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn coverage && \
|
||||
mkdir -p /node/src/app/build/api && cd /node/src/app/build/api/ && touch index.html openapi.yml
|
||||
|
||||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{.Base}}/api/swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="{{.Base}}/api/favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="{{.Base}}/api/favicon-16x16.png" sizes="16x16" />
|
||||
<style nonce="{{.CSPNonce}}">
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="{{.Base}}/api/swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||
<script src="{{.Base}}/api/swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
window.onload = function() {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "{{.Base}}/api/openapi.yml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,752 @@
|
|||
---
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Authelia API
|
||||
description: Authelia is an open-source authentication and authorization server providing 2-factor authentication and single sign-on (SSO) for your applications via a web portal.
|
||||
contact:
|
||||
name: Authelia Support
|
||||
url: https://github.com/authelia/authelia#contact-options
|
||||
email: team@authelia.com
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0
|
||||
version: 1.0.0
|
||||
tags:
|
||||
- name: State
|
||||
description: Configuration, health and state endpoints
|
||||
- name: Authentication
|
||||
description: Authentication and verification endpoints
|
||||
- name: Password Reset
|
||||
description: Password reset endpoints
|
||||
- name: User Information
|
||||
description: User configuration endpoints
|
||||
- name: Second Factor
|
||||
description: TOTP, U2F and Duo endpoints
|
||||
paths:
|
||||
/api/configuration:
|
||||
get:
|
||||
tags:
|
||||
- State
|
||||
summary: Application Configuration
|
||||
description: The configuration endpoint provides detailed information including available second factor methods, if any second factor policies exist and the TOTP period configuration.
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.configuration.ConfigurationBody'
|
||||
"403":
|
||||
description: Forbidden
|
||||
security:
|
||||
- authelia_auth: [ ]
|
||||
/api/health:
|
||||
get:
|
||||
tags:
|
||||
- State
|
||||
summary: Application Health
|
||||
description: The health check endpoint provides information about the health of Authelia.
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
/api/state:
|
||||
get:
|
||||
tags:
|
||||
- State
|
||||
summary: User Application State
|
||||
description: The state endpoint provides detailed information including the user, current authenticate level and Authelia's configured default redirection URL.
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.StateResponse'
|
||||
/api/verify:
|
||||
get:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: Verification
|
||||
description: The verify endpoint provides the ability to verify if a user has the necessary permissions to access a specified domain.
|
||||
parameters:
|
||||
- name: X-Original-URL
|
||||
in: header
|
||||
description: Redirection URL
|
||||
required: true
|
||||
style: simple
|
||||
explode: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
headers:
|
||||
remote-user:
|
||||
description: Username
|
||||
schema:
|
||||
type: string
|
||||
example: john
|
||||
remote-name:
|
||||
description: Name
|
||||
schema:
|
||||
type: string
|
||||
example: John Doe
|
||||
remote-email:
|
||||
description: Email
|
||||
schema:
|
||||
type: string
|
||||
example: john.doe@authelia.com
|
||||
remote-groups:
|
||||
description: Comma separated list of Groups
|
||||
schema:
|
||||
type: string
|
||||
example: admin,devs
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
head:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: Verification
|
||||
description: The verify endpoint provides the ability to verify if a user has the necessary permissions to access a specified domain.
|
||||
parameters:
|
||||
- name: X-Original-URL
|
||||
in: header
|
||||
description: Redirection URL
|
||||
required: true
|
||||
style: simple
|
||||
explode: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
headers:
|
||||
remote-user:
|
||||
description: Username
|
||||
schema:
|
||||
type: string
|
||||
example: john
|
||||
remote-name:
|
||||
description: Name
|
||||
schema:
|
||||
type: string
|
||||
example: John Doe
|
||||
remote-email:
|
||||
description: Email
|
||||
schema:
|
||||
type: string
|
||||
example: john.doe@authelia.com
|
||||
remote-groups:
|
||||
description: Comma separated list of Groups
|
||||
schema:
|
||||
type: string
|
||||
example: admin,devs
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/firstfactor:
|
||||
post:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: Login
|
||||
description: The firstfactor endpoint allows a user to login and generates an authentication cookie for authorization.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.firstFactorRequestBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
headers:
|
||||
Set-Cookie:
|
||||
style: simple
|
||||
explode: false
|
||||
schema:
|
||||
type: string
|
||||
example: authelia_session=kTTCSLupEUirZVfLeZTijezewFQnNOgs; Path=/
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.redirectResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/logout:
|
||||
post:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: Logout
|
||||
description: The logout endpoint allows a user to logout and destroy a sesssion.
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: [ ]
|
||||
/api/reset-password/identity/start:
|
||||
post:
|
||||
tags:
|
||||
- Password Reset
|
||||
summary: Identity Verification Token Creation
|
||||
description: "This endpoint is step 1 of 3 in the password reset process.\n\nIt validates the user session and sends the user an email with a token and a link to reset their password. This step also generates a session cookie for the rest of the process.\n\nThe same session cookie must be used for all steps in this process."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.resetPasswordStep1RequestBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/reset-password/identity/finish:
|
||||
post:
|
||||
tags:
|
||||
- Password Reset
|
||||
summary: Identity Verification Token Validation
|
||||
description: "This endpoint is step 2 of 3 in the password reset process.\n\nIt validates the user session and reset token.\n\nThe same session cookie must be used for all steps in this process."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.IdentityVerificationFinishBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/reset-password:
|
||||
post:
|
||||
tags:
|
||||
- Password Reset
|
||||
summary: Password Reset
|
||||
description: "This endpoint is step 3 of 3 in the password reset process.\n\nIt validates the user session and changes the password.\n\nThe same session cookie must be used for all steps in this process."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.resetPasswordStep2RequestBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/user/info:
|
||||
get:
|
||||
tags:
|
||||
- User Information
|
||||
summary: User Configuration
|
||||
description: The user info endpoint provides detailed information including a users display name, preferred and registered second factor method(s).
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.UserInfo'
|
||||
"403":
|
||||
description: Forbidden
|
||||
security:
|
||||
- authelia_auth: [ ]
|
||||
/api/user/info/2fa_method:
|
||||
post:
|
||||
tags:
|
||||
- User Information
|
||||
summary: User Configuration
|
||||
description: The user info 2fa_method endpoint sets the users preferred second factor method.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.UserInfo.MethodBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
"403":
|
||||
description: Forbidden
|
||||
security:
|
||||
- authelia_auth: [ ]
|
||||
/api/secondfactor/totp/identity/start:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Identity Verification TOTP Token Creation
|
||||
description: "This endpoint performs identity verification to begin the TOTP device registration process.\n\nThe session generated from this endpoint must be utilised for the subsequent step in the `/api/secondfactor/totp/identity/finish` endpoint."
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/totp/identity/finish:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Identity Verification TOTP Token Validation and Device Creation
|
||||
description: "This endpoint performs identity and token verification, upon success also generates TOTP device secret and registers said device.\n\nThe session cookie generated from the `/api/secondfactor/totp/identity/start` endpoint must be utilised for the step here"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.IdentityVerificationFinishBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.TOTPKeyResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/totp:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Second Factor Authentication - TOTP
|
||||
description: "This endpoint performs second factor authentication with a TOTP key."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.signTOTPRequestBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.redirectResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.ErrorResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/u2f/sign_request:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Second Factor Authentication - U2F (Request)
|
||||
description: "This endpoint starts the second factor authentication process with the U2F key."
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/u2f.WebSignRequest'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/u2f/sign:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Second Factor Authentication - U2F
|
||||
description: "This endpoint completes second factor authentication with a U2F key."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/handlers.signU2FRequestBody"
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.redirectResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/u2f/identity/start:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Identity Verification U2F Token Creation
|
||||
description: "This endpoint performs identity verification to begin the U2F device registration process.\n\nThe session generated from this endpoint must be utilised for the subsequent steps in the `/api/secondfactor/u2f/identity/finish` and `/api/secondfactor/u2f/register` endpoints."
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/u2f/identity/finish:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Identity Verification U2F Token Validation
|
||||
description: "This endpoint performs identity and token verification, upon success generates a U2F device registration challenge.\n\nThe session cookie generated from the `/api/secondfactor/u2f/identity/start` endpoint must be utilised for the subsequent steps here and in the `/api/secondfactor/u2f/register` endpoint."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.IdentityVerificationFinishBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/u2f.WebRegisterRequest'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/u2f/register:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: U2F Device Registration
|
||||
description: "This endpoint performs U2F device registration."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/u2f.RegisterResponse'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/middlewares.OkResponse'
|
||||
security:
|
||||
- authelia_auth: []
|
||||
/api/secondfactor/duo:
|
||||
post:
|
||||
tags:
|
||||
- Second Factor
|
||||
summary: Second Factor Authentication - Duo Mobile Push
|
||||
description: "This endpoint performs second factor authentication with a Duo Mobile Push."
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.signDuoRequestBody'
|
||||
responses:
|
||||
"200":
|
||||
description: Successful Operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/handlers.redirectResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
security:
|
||||
- authelia_auth: []
|
||||
components:
|
||||
schemas:
|
||||
handlers.configuration.ConfigurationBody:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
available_methods:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: [totp, u2f, mobile_push]
|
||||
second_factor_enabled:
|
||||
type: boolean
|
||||
description: If second factor is enabled.
|
||||
totp_period:
|
||||
type: integer
|
||||
example: 30
|
||||
handlers.firstFactorRequestBody:
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: john
|
||||
password:
|
||||
type: string
|
||||
example: password
|
||||
targetURL:
|
||||
type: string
|
||||
example: https://home.example.com
|
||||
keepMeLoggedIn:
|
||||
type: boolean
|
||||
example: true
|
||||
handlers.redirectResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
redirect:
|
||||
type: string
|
||||
example: https://home.example.com
|
||||
handlers.resetPasswordStep1RequestBody:
|
||||
required:
|
||||
- username
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: john
|
||||
handlers.resetPasswordStep2RequestBody:
|
||||
required:
|
||||
- password
|
||||
type: object
|
||||
properties:
|
||||
password:
|
||||
type: string
|
||||
example: password
|
||||
handlers.signDuoRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
targetURL:
|
||||
type: string
|
||||
example: https://secure.example.com
|
||||
handlers.signTOTPRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
example: "123456"
|
||||
targetURL:
|
||||
type: string
|
||||
example: https://secure.example.com
|
||||
handlers.signU2FRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
targetURL:
|
||||
type: string
|
||||
example: https://secure.example.com
|
||||
signResponse:
|
||||
type: object
|
||||
properties:
|
||||
clientData:
|
||||
type: string
|
||||
example: 6prxyWqSsR6MXFchtQRzwZVTedWq7Zdc6XreLt6xRDXKeqJN7vzKAfYcKwRD3AT57bP4YFL4hbxat4LUysBNss
|
||||
keyHandle:
|
||||
type: string
|
||||
example: pWgBrwr9meS5vArdffPtD4Px6AqZS7MfGEf776Rz438ujwHjeXwQEZuK53sRQ4wjeAgRCW4wX9VRj8dyKjc273
|
||||
signatureData:
|
||||
type: string
|
||||
example: p3Pe26B6T2E7EEEc59P4p869qwxy8cQAU2ttyGtGrQHb4XL2ZxCpWrawsSHNSTRZQd7jEW59Y3Ku9vSNRzj7Ly
|
||||
handlers.StateResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: john
|
||||
authentication_level:
|
||||
type: integer
|
||||
example: 1
|
||||
default_redirection_url:
|
||||
type: string
|
||||
example: https://home.example.com
|
||||
handlers.TOTPKeyResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
base32_secret:
|
||||
type: string
|
||||
example: 5ZH7Y5CTFWOXN7EOLGBMMXADRNQFHVUDZSYKCN5HMFAIRSLAWY3Q
|
||||
otpauth_url:
|
||||
type: string
|
||||
example: otpauth://totp/auth.example.com:john?algorithm=SHA1&digits=6&issuer=auth.example.com&period=30&secret=5ZH7Y5CTFWOXN7EOLGBMMXADRNQFHVUDZSYKCN5HMFAIRSLAWY3Q
|
||||
handlers.UserInfo:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
display_name:
|
||||
type: string
|
||||
example: John Doe
|
||||
method:
|
||||
type: string
|
||||
enum: [totp, u2f, mobile_push]
|
||||
example: totp
|
||||
has_u2f:
|
||||
type: boolean
|
||||
example: false
|
||||
has_totp:
|
||||
type: boolean
|
||||
example: true
|
||||
handlers.UserInfo.MethodBody:
|
||||
required:
|
||||
- method
|
||||
type: object
|
||||
properties:
|
||||
method:
|
||||
type: string
|
||||
enum: [totp, u2f, mobile_push]
|
||||
example: totp
|
||||
middlewares.ErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: KO
|
||||
message:
|
||||
type: string
|
||||
example: Authentication failed, please retry later.
|
||||
middlewares.IdentityVerificationFinishBody:
|
||||
required:
|
||||
- token
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDc5MjU1OTYsImlzcyI6IkF1dGhlbGlhIiwiYWN0aW9uIjoiUmVzZXRQYXNzd29yZCIsInVzZXJuYW1lIjoiQW1pciJ9.636yqRrUCGCe4jsMCsonleX5CYWHncYqZum-YYb6VaY
|
||||
middlewares.OkResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
u2f.RegisterResponse:
|
||||
type: object
|
||||
properties:
|
||||
version:
|
||||
type: string
|
||||
registrationData:
|
||||
type: string
|
||||
clientData:
|
||||
type: string
|
||||
u2f.WebRegisterRequest:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
appId:
|
||||
type: string
|
||||
example: https://auth.example.com
|
||||
registerRequests:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
version:
|
||||
type: string
|
||||
example: U2F_V2
|
||||
challenge:
|
||||
type: string
|
||||
example: XGYKUzSmTpM1KxxpekArviW0w0OU2pwwRAocgn8TkVQ
|
||||
registeredKeys:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
appId:
|
||||
type: string
|
||||
example: https://auth.example.com
|
||||
version:
|
||||
type: string
|
||||
example: U2F_V2
|
||||
keyHandle:
|
||||
type: string
|
||||
example: pWgBrwr9meS5vArdffPtD4Px6AqZS7MfGEf776Rz438ujwHjeXwQEZuK53sRQ4wjeAgRCW4wX9VRj8dyKjc273
|
||||
u2f.WebSignRequest:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: OK
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
appId:
|
||||
type: string
|
||||
example: https://auth.example.com
|
||||
challenge:
|
||||
type: string
|
||||
example: XGYKUzSmTpM1KxxpekArviW0w0OU2pwwRAocgn8TkVQ
|
||||
registeredKeys:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
appId:
|
||||
type: string
|
||||
example: https://auth.example.com
|
||||
version:
|
||||
type: string
|
||||
example: U2F_V2
|
||||
keyHandle:
|
||||
type: string
|
||||
example: pWgBrwr9meS5vArdffPtD4Px6AqZS7MfGEf776Rz438ujwHjeXwQEZuK53sRQ4wjeAgRCW4wX9VRj8dyKjc273
|
||||
securitySchemes:
|
||||
authelia_auth:
|
||||
type: apiKey
|
||||
name: "{{.Session}}"
|
||||
in: cookie
|
|
@ -17,32 +17,63 @@ func buildAutheliaBinary() {
|
|||
"GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=1")
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildFrontend() {
|
||||
// Install npm dependencies.
|
||||
cmd := utils.CommandWithStdout("yarn", "install")
|
||||
cmd.Dir = webDirectory
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Then build the frontend.
|
||||
cmd = utils.CommandWithStdout("yarn", "build")
|
||||
cmd.Dir = webDirectory
|
||||
|
||||
cmd.Env = append(os.Environ(), "INLINE_RUNTIME_CHUNK=false")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.Rename("web/build", "./public_html"); err != nil {
|
||||
err = os.Rename("web/build", "./public_html")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildSwagger() {
|
||||
swaggerVer := "3.38.0"
|
||||
cmd := utils.CommandWithStdout("bash", "-c", "wget -q https://github.com/swagger-api/swagger-ui/archive/v"+swaggerVer+".tar.gz -O ./v"+swaggerVer+".tar.gz")
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = utils.CommandWithStdout("cp", "-r", "api", "public_html")
|
||||
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = utils.CommandWithStdout("tar", "-C", swaggerDirectory, "--exclude=index.html", "--strip-components=2", "-xf", "v"+swaggerVer+".tar.gz", "swagger-ui-"+swaggerVer+"/dist")
|
||||
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = utils.CommandWithStdout("rm", "./v"+swaggerVer+".tar.gz")
|
||||
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -51,30 +82,28 @@ func generateEmbeddedAssets() {
|
|||
cmd := utils.CommandWithStdout("go", "get", "-u", "aletheia.icu/broccoli")
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = utils.CommandWithStdout("go", "generate", ".")
|
||||
cmd.Dir = "internal/configuration"
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = utils.CommandWithStdout("go", "generate", ".")
|
||||
cmd.Dir = "internal/server"
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.Rename("./public_html", OutputDir+"/public_html"); err != nil {
|
||||
err = os.Rename("./public_html", OutputDir+"/public_html")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -89,12 +118,15 @@ func Build(cobraCmd *cobra.Command, args []string) {
|
|||
err := os.MkdirAll(OutputDir, os.ModePerm)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Debug("Building Authelia frontend...")
|
||||
buildFrontend()
|
||||
|
||||
log.Debug("Building swagger-ui frontend...")
|
||||
buildSwagger()
|
||||
|
||||
log.Debug("Building Authelia Go binary...")
|
||||
generateEmbeddedAssets()
|
||||
buildAutheliaBinary()
|
||||
|
|
|
@ -12,4 +12,5 @@ var IntermediateDockerImageName = "authelia:dist"
|
|||
const masterTag = "master"
|
||||
const stringFalse = "false"
|
||||
const stringTrue = "true"
|
||||
const swaggerDirectory = "public_html/api"
|
||||
const webDirectory = "web"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
package server
|
||||
|
||||
const apiFile = "openapi.yml"
|
||||
const indexFile = "index.html"
|
||||
|
||||
const dev = "dev"
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
|
||||
"github.com/authelia/authelia/internal/logging"
|
||||
"github.com/authelia/authelia/internal/utils"
|
||||
)
|
||||
|
||||
var alphaNumericRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
// ServeIndex serve the index.html file with nonce generated for supporting
|
||||
// restrictive CSP while using material-ui from the embedded virtual filesystem.
|
||||
//go:generate broccoli -src ../../public_html -o public_html
|
||||
func ServeIndex(publicDir, base, rememberMe, resetPassword string) fasthttp.RequestHandler {
|
||||
f, err := br.Open(publicDir + "/index.html")
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to open index.html: %v", err)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to read index.html: %v", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("index").Parse(string(b))
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to parse index.html template: %v", err)
|
||||
}
|
||||
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
nonce := utils.RandomString(32, alphaNumericRunes)
|
||||
|
||||
ctx.SetContentType("text/html; charset=utf-8")
|
||||
|
||||
if os.Getenv("ENVIRONMENT") == dev {
|
||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
||||
} else {
|
||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self'; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
||||
}
|
||||
|
||||
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, CSPNonce, RememberMe, ResetPassword string }{Base: base, CSPNonce: nonce, RememberMe: rememberMe, ResetPassword: resetPassword})
|
||||
if err != nil {
|
||||
ctx.Error("An error occurred", 503)
|
||||
logging.Logger().Errorf("Unable to execute template: %v", err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,4 +4,4 @@ import "aletheia.icu/broccoli/fs"
|
|||
|
||||
// Mock the embedded filesystem for unit tests. The bundle is built from an empty file and
|
||||
// allows to run the dev workflow without failure.
|
||||
var br = fs.New(false, []byte("\x1b~\x00\x80\x8d\x94n\xc2|\x84J\xf7\xbfn\xfd\xf7w;.\x8d m\xb2&\xd1Z\xec\xb2\x05\xb9\xc00\x8a\xf7(\x80^78\t(\f\f\xc3p\xc2\xc1\x06[a\xa2\xb3\xa4P\xe5\xa14\xfb\x19\xb2cp\xf6\x90-Z\xb2\x11\xe0l\xa1\x80\\\x95Vh\t\xc5\x06\x16\xfa\x8c\xc0\"!\xa5\xcf\xf7$\x9a\xb2\a`\xc6\x18\xc8~\xce8\r\x16Z\x9d\xc3\xe3\xff\x00"))
|
||||
var br = fs.New(false, []byte("\x1b\xf7\x00\x00ħ?\xf5\xbd\xaci\x936'\x9e\x8b\xe5*\xda\xfbֵ@6\x96\xa0\"e\xc9xz\x92eaH)\aA\x18a`m\xcd#\xfd\xc1\xbe\x1d\xe4h\x87:\xd9h/2~\x17\x92'w~J\x94\xe6\x178?\x80n\xbe˔\xea@\x95J/n\x82V\xfa\x02\x1etB\x81\xa0t\xa2·\xf5\xfe\x02̿\xf9\x05E\xb2Q\xcb\xe5\xea\xb6\xdfQ\xdfS\n\x0e\xff蓼\xe4\xefR-Nkʍ\x1d\xed\xd5 [&*\x0f\f\x83\xd6\xec\x92\v\x1b\x19\xb4\x1d\x91\x00"))
|
||||
|
|
|
@ -25,22 +25,28 @@ import (
|
|||
// StartServer start Authelia server with the given configuration and providers.
|
||||
func StartServer(configuration schema.Configuration, providers middlewares.Providers) {
|
||||
autheliaMiddleware := middlewares.AutheliaMiddleware(configuration, providers)
|
||||
embeddedAssets := "/public_html"
|
||||
embeddedAssets := "/public_html/"
|
||||
swaggerAssets := embeddedAssets + "api/"
|
||||
rememberMe := strconv.FormatBool(configuration.Session.RememberMeDuration != "0")
|
||||
resetPassword := strconv.FormatBool(!configuration.AuthenticationBackend.DisableResetPassword)
|
||||
|
||||
rootFiles := []string{"favicon.ico", "manifest.json", "robots.txt"}
|
||||
|
||||
serveIndexHandler := ServeIndex(embeddedAssets, configuration.Server.Path, rememberMe, resetPassword)
|
||||
serveIndexHandler := ServeTemplatedFile(embeddedAssets, indexFile, configuration.Server.Path, configuration.Session.Name, rememberMe, resetPassword)
|
||||
serveSwaggerHandler := ServeTemplatedFile(swaggerAssets, indexFile, configuration.Server.Path, configuration.Session.Name, rememberMe, resetPassword)
|
||||
serveSwaggerAPIHandler := ServeTemplatedFile(swaggerAssets, apiFile, configuration.Server.Path, configuration.Session.Name, rememberMe, resetPassword)
|
||||
|
||||
r := router.New()
|
||||
r.GET("/", serveIndexHandler)
|
||||
r.GET("/api/", serveSwaggerHandler)
|
||||
r.GET("/api/"+apiFile, serveSwaggerAPIHandler)
|
||||
|
||||
for _, f := range rootFiles {
|
||||
r.GET("/"+f, fasthttpadaptor.NewFastHTTPHandler(br.Serve(embeddedAssets)))
|
||||
}
|
||||
|
||||
r.GET("/static/{filepath:*}", fasthttpadaptor.NewFastHTTPHandler(br.Serve(embeddedAssets)))
|
||||
r.GET("/api/{filepath:*}", fasthttpadaptor.NewFastHTTPHandler(br.Serve(embeddedAssets)))
|
||||
|
||||
r.GET("/api/health", autheliaMiddleware(handlers.HealthGet))
|
||||
r.GET("/api/state", autheliaMiddleware(handlers.StateGet))
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
|
||||
"github.com/authelia/authelia/internal/logging"
|
||||
"github.com/authelia/authelia/internal/utils"
|
||||
)
|
||||
|
||||
var alphaNumericRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
// ServeTemplatedFile serves a templated version of a specified file,
|
||||
// this is utilised to pass information between the backend and frontend
|
||||
// and generate a nonce to support a restrictive CSP while using material-ui.
|
||||
//go:generate broccoli -src ../../public_html -o public_html
|
||||
func ServeTemplatedFile(publicDir, file, base, session, rememberMe, resetPassword string) fasthttp.RequestHandler {
|
||||
f, err := br.Open(publicDir + file)
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to open %s: %s", file, err)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to read %s: %s", file, err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("file").Parse(string(b))
|
||||
if err != nil {
|
||||
logging.Logger().Fatalf("Unable to parse %s template: %s", file, err)
|
||||
}
|
||||
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
nonce := utils.RandomString(32, alphaNumericRunes)
|
||||
|
||||
switch extension := filepath.Ext(file); extension {
|
||||
case ".html":
|
||||
ctx.SetContentType("text/html; charset=utf-8")
|
||||
default:
|
||||
ctx.SetContentType("text/plain; charset=utf-8")
|
||||
}
|
||||
|
||||
switch {
|
||||
case os.Getenv("ENVIRONMENT") == dev:
|
||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
||||
case publicDir == "/public_html/api/":
|
||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("base-uri 'self' ; default-src 'self' ; img-src 'self' https://validator.swagger.io data: ; object-src 'none' ; script-src 'self' 'unsafe-inline' 'nonce-%s' ; style-src 'self' 'nonce-%s'", nonce, nonce))
|
||||
default:
|
||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("default-src 'self' ; object-src 'none'; style-src 'self' 'nonce-%s'", nonce))
|
||||
}
|
||||
|
||||
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, CSPNonce, Session, RememberMe, ResetPassword string }{Base: base, CSPNonce: nonce, Session: session, RememberMe: rememberMe, ResetPassword: resetPassword})
|
||||
if err != nil {
|
||||
ctx.Error("An error occurred", 503)
|
||||
logging.Logger().Errorf("Unable to execute template: %v", err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.eslintcache
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
|
Loading…
Reference in New Issue