diff --git a/pkg/modules/auth/openid/openid.go b/pkg/modules/auth/openid/openid.go index 6430ff3fb..b68527a60 100644 --- a/pkg/modules/auth/openid/openid.go +++ b/pkg/modules/auth/openid/openid.go @@ -144,6 +144,17 @@ func GetProvider(key string) (*Provider, error) { } // HandleCallback handles the auth request callback after redirecting from the provider with an auth code +// @Summary Authenticate a user with OpenID Connect +// @Description After a redirect from the OpenID Connect provider to the frontend has been made with the authentication `code`, this endpoint can be used to obtain a jwt token for that user and thus log them in. +// @tags auth +// @Accept json +// @Produce json +// @Security JWTKeyAuth +// @Param callback body openid.Callback true "The openid callback" +// @Param provider path int true "The OpenID Connect provider key as returned by the /info endpoint" +// @Success 200 {object} auth.Token +// @Failure 500 {object} models.Message "Internal error" +// @Router /auth/openid/{provider}/callback [post] func HandleCallback(c echo.Context) error { cb := &Callback{} if err := c.Bind(cb); err != nil { diff --git a/pkg/routes/api/v1/link_sharing_auth.go b/pkg/routes/api/v1/link_sharing_auth.go index 9e2a6f643..0040cfecb 100644 --- a/pkg/routes/api/v1/link_sharing_auth.go +++ b/pkg/routes/api/v1/link_sharing_auth.go @@ -39,7 +39,7 @@ type LinkShareToken struct { // @Accept json // @Produce json // @Param share path string true "The share hash" -// @Success 200 {object} v1.Token "The valid jwt auth token." +// @Success 200 {object} auth.Token "The valid jwt auth token." // @Failure 400 {object} web.HTTPError "Invalid link share object provided." // @Failure 500 {object} models.Message "Internal error" // @Router /shares/{share}/auth [post] diff --git a/pkg/routes/api/v1/login.go b/pkg/routes/api/v1/login.go index a5bb37772..79ab6ae79 100644 --- a/pkg/routes/api/v1/login.go +++ b/pkg/routes/api/v1/login.go @@ -34,7 +34,7 @@ import ( // @Accept json // @Produce json // @Param credentials body user.Login true "The login credentials" -// @Success 200 {object} v1.Token +// @Success 200 {object} auth.Token // @Failure 400 {object} models.Message "Invalid user password model." // @Failure 412 {object} models.Message "Invalid totp passcode." // @Failure 403 {object} models.Message "Invalid username or password." @@ -77,7 +77,7 @@ func Login(c echo.Context) error { // @tags user // @Accept json // @Produce json -// @Success 200 {object} v1.Token +// @Success 200 {object} auth.Token // @Failure 400 {object} models.Message "Only user token are available for renew." // @Router /user/token [post] func RenewToken(c echo.Context) (err error) { diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go index be130778a..516fd0ec9 100644 --- a/pkg/swagger/docs.go +++ b/pkg/swagger/docs.go @@ -32,6 +32,58 @@ var doc = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/auth/openid/{provider}/callback": { + "post": { + "security": [ + { + "JWTKeyAuth": [] + } + ], + "description": "After a redirect from the OpenID Connect provider to the frontend has been made with the authentication ` + "`" + `code` + "`" + `, this endpoint can be used to obtain a jwt token for that user and thus log them in.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Authenticate a user with OpenID Connect", + "parameters": [ + { + "description": "The openid callback", + "name": "callback", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/openid.Callback" + } + }, + { + "type": "integer", + "description": "The OpenID Connect provider key as returned by the /info endpoint", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.Token" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "#/definitions/models.Message" + } + } + } + } + }, "/backgrounds/unsplash/image/{image}": { "get": { "security": [ @@ -2426,7 +2478,7 @@ var doc = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -3671,7 +3723,7 @@ var doc = `{ "200": { "description": "The valid jwt auth token.", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -6240,7 +6292,7 @@ var doc = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -6352,6 +6404,14 @@ var doc = `{ } }, "definitions": { + "auth.Token": { + "type": "object", + "properties": { + "token": { + "type": "string" + } + } + }, "background.Image": { "type": "object", "properties": { @@ -7430,6 +7490,34 @@ var doc = `{ } } }, + "openid.Callback": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "openid.Provider": { + "type": "object", + "properties": { + "auth_url": { + "type": "string" + }, + "client_id": { + "type": "string" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "todoist.Migration": { "type": "object", "properties": { @@ -7577,14 +7665,6 @@ var doc = `{ } } }, - "v1.Token": { - "type": "object", - "properties": { - "token": { - "type": "string" - } - } - }, "v1.UserAvatarProvider": { "type": "object", "properties": { @@ -7604,6 +7684,17 @@ var doc = `{ } } }, + "v1.authInfo": { + "type": "object", + "properties": { + "local": { + "$ref": "#/definitions/v1.localAuthInfo" + }, + "openid_connect": { + "$ref": "#/definitions/v1.openIDAuthInfo" + } + } + }, "v1.legalInfo": { "type": "object", "properties": { @@ -7615,9 +7706,37 @@ var doc = `{ } } }, + "v1.localAuthInfo": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "v1.openIDAuthInfo": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "providers": { + "type": "array", + "items": { + "$ref": "#/definitions/openid.Provider" + } + }, + "redirect_url": { + "type": "string" + } + } + }, "v1.vikunjaInfos": { "type": "object", "properties": { + "auth": { + "$ref": "#/definitions/v1.authInfo" + }, "available_migrators": { "type": "array", "items": { diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json index a51e09464..d152ead80 100644 --- a/pkg/swagger/swagger.json +++ b/pkg/swagger/swagger.json @@ -15,6 +15,58 @@ }, "basePath": "/api/v1", "paths": { + "/auth/openid/{provider}/callback": { + "post": { + "security": [ + { + "JWTKeyAuth": [] + } + ], + "description": "After a redirect from the OpenID Connect provider to the frontend has been made with the authentication `code`, this endpoint can be used to obtain a jwt token for that user and thus log them in.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Authenticate a user with OpenID Connect", + "parameters": [ + { + "description": "The openid callback", + "name": "callback", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/openid.Callback" + } + }, + { + "type": "integer", + "description": "The OpenID Connect provider key as returned by the /info endpoint", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.Token" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "#/definitions/models.Message" + } + } + } + } + }, "/backgrounds/unsplash/image/{image}": { "get": { "security": [ @@ -2409,7 +2461,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -3654,7 +3706,7 @@ "200": { "description": "The valid jwt auth token.", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -6223,7 +6275,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Token" + "$ref": "#/definitions/auth.Token" } }, "400": { @@ -6335,6 +6387,14 @@ } }, "definitions": { + "auth.Token": { + "type": "object", + "properties": { + "token": { + "type": "string" + } + } + }, "background.Image": { "type": "object", "properties": { @@ -7413,6 +7473,34 @@ } } }, + "openid.Callback": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "openid.Provider": { + "type": "object", + "properties": { + "auth_url": { + "type": "string" + }, + "client_id": { + "type": "string" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "todoist.Migration": { "type": "object", "properties": { @@ -7560,14 +7648,6 @@ } } }, - "v1.Token": { - "type": "object", - "properties": { - "token": { - "type": "string" - } - } - }, "v1.UserAvatarProvider": { "type": "object", "properties": { @@ -7587,6 +7667,17 @@ } } }, + "v1.authInfo": { + "type": "object", + "properties": { + "local": { + "$ref": "#/definitions/v1.localAuthInfo" + }, + "openid_connect": { + "$ref": "#/definitions/v1.openIDAuthInfo" + } + } + }, "v1.legalInfo": { "type": "object", "properties": { @@ -7598,9 +7689,37 @@ } } }, + "v1.localAuthInfo": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "v1.openIDAuthInfo": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "providers": { + "type": "array", + "items": { + "$ref": "#/definitions/openid.Provider" + } + }, + "redirect_url": { + "type": "string" + } + } + }, "v1.vikunjaInfos": { "type": "object", "properties": { + "auth": { + "$ref": "#/definitions/v1.authInfo" + }, "available_migrators": { "type": "array", "items": { diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml index a602d274e..37f059dba 100644 --- a/pkg/swagger/swagger.yaml +++ b/pkg/swagger/swagger.yaml @@ -1,5 +1,10 @@ basePath: /api/v1 definitions: + auth.Token: + properties: + token: + type: string + type: object background.Image: properties: id: @@ -795,6 +800,24 @@ definitions: minLength: 1 type: string type: object + openid.Callback: + properties: + code: + type: string + scope: + type: string + type: object + openid.Provider: + properties: + auth_url: + type: string + client_id: + type: string + key: + type: string + name: + type: string + type: object todoist.Migration: properties: code: @@ -899,11 +922,6 @@ definitions: minLength: 1 type: string type: object - v1.Token: - properties: - token: - type: string - type: object v1.UserAvatarProvider: properties: avatar_provider: @@ -916,6 +934,13 @@ definitions: old_password: type: string type: object + v1.authInfo: + properties: + local: + $ref: '#/definitions/v1.localAuthInfo' + openid_connect: + $ref: '#/definitions/v1.openIDAuthInfo' + type: object v1.legalInfo: properties: imprint_url: @@ -923,8 +948,26 @@ definitions: privacy_policy_url: type: string type: object + v1.localAuthInfo: + properties: + enabled: + type: boolean + type: object + v1.openIDAuthInfo: + properties: + enabled: + type: boolean + providers: + items: + $ref: '#/definitions/openid.Provider' + type: array + redirect_url: + type: string + type: object v1.vikunjaInfos: properties: + auth: + $ref: '#/definitions/v1.authInfo' available_migrators: items: type: string @@ -1021,6 +1064,39 @@ paths: summary: User Avatar tags: - user + /auth/openid/{provider}/callback: + post: + consumes: + - application/json + description: After a redirect from the OpenID Connect provider to the frontend has been made with the authentication `code`, this endpoint can be used to obtain a jwt token for that user and thus log them in. + parameters: + - description: The openid callback + in: body + name: callback + required: true + schema: + $ref: '#/definitions/openid.Callback' + - description: The OpenID Connect provider key as returned by the /info endpoint + in: path + name: provider + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/auth.Token' + "500": + description: Internal error + schema: + $ref: '#/definitions/models.Message' + security: + - JWTKeyAuth: [] + summary: Authenticate a user with OpenID Connect + tags: + - auth /backgrounds/unsplash/image/{image}: get: description: Get an unsplash image. **Returns json on error.** @@ -2558,7 +2634,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/v1.Token' + $ref: '#/definitions/auth.Token' "400": description: Invalid user password model. schema: @@ -3354,7 +3430,7 @@ paths: "200": description: The valid jwt auth token. schema: - $ref: '#/definitions/v1.Token' + $ref: '#/definitions/auth.Token' "400": description: Invalid link share object provided. schema: @@ -4997,7 +5073,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/v1.Token' + $ref: '#/definitions/auth.Token' "400": description: Only user token are available for renew. schema: