|
| 1 | +### Example with feathers generated authentication on feathersjs v5 (dove) <!-- {docsify-ignore} --> |
| 2 | + |
| 3 | +1. When you have generated the app with authentication you have to add some things to the initial |
| 4 | + specs when registering feathers swagger. |
| 5 | + |
| 6 | + ```typescript |
| 7 | + app.configure( |
| 8 | + swagger({ |
| 9 | + specs: { |
| 10 | + info: { |
| 11 | + title: 'Feathers app with swagger with authentication', |
| 12 | + version: '1.0.0', |
| 13 | + description: '...', |
| 14 | + }, |
| 15 | + components: { |
| 16 | + securitySchemes: { |
| 17 | + BearerAuth: { |
| 18 | + type: 'http', |
| 19 | + scheme: 'bearer', |
| 20 | + }, |
| 21 | + }, |
| 22 | + }, |
| 23 | + security: [{ BearerAuth: [] }], |
| 24 | + }, |
| 25 | + // other options ... |
| 26 | + }), |
| 27 | + ); |
| 28 | + ``` |
| 29 | + |
| 30 | +2. Add documentation to the authentication service (`src/authentication.ts`). |
| 31 | + This example shows local authentication. |
| 32 | + |
| 33 | + ```typescript |
| 34 | + import { AuthenticationService, JWTStrategy } from '@feathersjs/authentication'; |
| 35 | + import { LocalStrategy } from '@feathersjs/authentication-local'; |
| 36 | + import type { Application } from './declarations'; |
| 37 | + import { ServiceSwaggerOptions } from '../../feathers-swagger'; |
| 38 | + |
| 39 | + declare module './declarations' { |
| 40 | + interface ServiceTypes { |
| 41 | + authentication: AuthenticationService; |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + declare module '@feathersjs/authentication' { |
| 46 | + class AuthenticationService { |
| 47 | + docs: ServiceSwaggerOptions; |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + export const authentication = (app: Application) => { |
| 52 | + const authentication = new AuthenticationService(app); |
| 53 | + |
| 54 | + authentication.docs = { |
| 55 | + idNames: { |
| 56 | + remove: 'accessToken', |
| 57 | + }, |
| 58 | + idType: 'string', |
| 59 | + securities: ['remove', 'removeMulti'], |
| 60 | + multi: ['remove'], |
| 61 | + schemas: { |
| 62 | + authRequest: { |
| 63 | + type: 'object', |
| 64 | + properties: { |
| 65 | + strategy: { type: 'string' }, |
| 66 | + email: { type: 'string' }, |
| 67 | + password: { type: 'string' }, |
| 68 | + }, |
| 69 | + }, |
| 70 | + authResult: { |
| 71 | + type: 'object', |
| 72 | + properties: { |
| 73 | + accessToken: { type: 'string' }, |
| 74 | + authentication: { |
| 75 | + type: 'object', |
| 76 | + properties: { |
| 77 | + strategy: { type: 'string' }, |
| 78 | + }, |
| 79 | + }, |
| 80 | + payload: { |
| 81 | + type: 'object', |
| 82 | + properties: {}, // TODO |
| 83 | + }, |
| 84 | + user: { $ref: '#/components/schemas/User' }, |
| 85 | + }, |
| 86 | + }, |
| 87 | + }, |
| 88 | + refs: { |
| 89 | + createRequest: 'authRequest', |
| 90 | + createResponse: 'authResult', |
| 91 | + removeResponse: 'authResult', |
| 92 | + removeMultiResponse: 'authResult', |
| 93 | + }, |
| 94 | + operations: { |
| 95 | + remove: { |
| 96 | + description: 'Logout the currently logged in user', |
| 97 | + 'parameters[0].description': 'accessToken of the currently logged in user', |
| 98 | + }, |
| 99 | + removeMulti: { |
| 100 | + description: 'Logout the currently logged in user', |
| 101 | + parameters: [], |
| 102 | + }, |
| 103 | + }, |
| 104 | + }; |
| 105 | + |
| 106 | + authentication.register('jwt', new JWTStrategy()); |
| 107 | + authentication.register('local', new LocalStrategy()); |
| 108 | + |
| 109 | + app.use('authentication', authentication); |
| 110 | + }; |
| 111 | + ``` |
| 112 | + |
| 113 | +3. Set the `security` option for `service.docs` like shown in |
| 114 | + [Using Schemas of Feathersjs v5 (dove)](/examples/generated_service_v5.md) for methods that are protected. |
| 115 | + If all methods are protected `all` can be used. |
| 116 | + |
| 117 | +4. If you want to provide simple authentication usage on the SwaggerUI using Email/Username and Password, |
| 118 | + you can use the [Swagger UI Plugin ApiKeyAuthForm](https://github.com/Mairu/swagger-ui-apikey-auth-form). |
| 119 | + |
| 120 | + Here is an example of an `openapi.ts` swagger configuration file, that can used with `api.configure()`; |
| 121 | + |
| 122 | + ```typescript |
| 123 | + import swagger, { FnSwaggerUiGetInitializerScript } from 'feathers-swagger'; |
| 124 | + import type { Application } from './declarations'; |
| 125 | + |
| 126 | + const getSwaggerInitializerScript: FnSwaggerUiGetInitializerScript = ({ docsJsonPath, ctx }) => { |
| 127 | + const headers = ctx && ctx.headers; |
| 128 | + const basePath = headers!['x-forwarded-prefix'] ?? ''; |
| 129 | + |
| 130 | + // language=JavaScript |
| 131 | + return ` |
| 132 | + window.onload = function () { |
| 133 | + var script = document.createElement('script'); |
| 134 | + script.onload = function () { |
| 135 | + window.ui = SwaggerUIBundle({ |
| 136 | + url: "${basePath}${docsJsonPath}", |
| 137 | + dom_id: '#swagger-ui', |
| 138 | + deepLinking: true, |
| 139 | + presets: [ |
| 140 | + SwaggerUIBundle.presets.apis, |
| 141 | + SwaggerUIStandalonePreset, |
| 142 | + SwaggerUIApiKeyAuthFormPlugin, |
| 143 | + ], |
| 144 | + plugins: [ |
| 145 | + SwaggerUIBundle.plugins.DownloadUrl |
| 146 | + ], |
| 147 | + layout: "StandaloneLayout", |
| 148 | + configs: { |
| 149 | + apiKeyAuthFormPlugin: { |
| 150 | + forms: { |
| 151 | + BearerAuth: { |
| 152 | + fields: { |
| 153 | + email: { |
| 154 | + type: 'text', |
| 155 | + label: 'E-Mail-Address', |
| 156 | + }, |
| 157 | + password: { |
| 158 | + type: 'password', |
| 159 | + label: 'Password', |
| 160 | + }, |
| 161 | + }, |
| 162 | + authCallback(values, callback) { |
| 163 | + window.ui.fn.fetch({ |
| 164 | + url: '/authentication', |
| 165 | + method: 'post', |
| 166 | + headers: { |
| 167 | + Accept: 'application/json', |
| 168 | + 'Content-Type': 'application/json' |
| 169 | + }, |
| 170 | + body: JSON.stringify({ |
| 171 | + strategy: 'local', |
| 172 | + ...values, |
| 173 | + }), |
| 174 | + }).then(function (response) { |
| 175 | + const json = JSON.parse(response.data); |
| 176 | + if (json.accessToken) { |
| 177 | + callback(null, json.accessToken); |
| 178 | + } else { |
| 179 | + callback('error while login'); |
| 180 | + } |
| 181 | + }).catch(function (err) { |
| 182 | + console.log(err, Object.entries(err)); |
| 183 | + callback('error while login'); |
| 184 | + }); |
| 185 | + }, |
| 186 | + } |
| 187 | + }, |
| 188 | + localStorage: { |
| 189 | + BearerAuth: {} |
| 190 | + } |
| 191 | + } |
| 192 | + } |
| 193 | + }); |
| 194 | + }; |
| 195 | + |
| 196 | + script.src = '//cdn.jsdelivr.net/npm/@mairu/swagger-ui-apikey-auth-form@1/dist/swagger-ui-apikey-auth-form.js'; |
| 197 | + document.head.appendChild(script) |
| 198 | + }; |
| 199 | + `; |
| 200 | + }; |
| 201 | + |
| 202 | + export default (app: Application) => { |
| 203 | + // If you don't use custom methods this line can be removed |
| 204 | + app.configure(swagger.customMethodsHandler); |
| 205 | + |
| 206 | + app.configure( |
| 207 | + swagger({ |
| 208 | + specs: { |
| 209 | + info: { |
| 210 | + title: 'Example with Authentication', |
| 211 | + version: '1.0.0', |
| 212 | + description: 'Example with Authentication and SwaggerUI ApiKeyAuthForm plugin', |
| 213 | + }, |
| 214 | + components: { |
| 215 | + securitySchemes: { |
| 216 | + BearerAuth: { |
| 217 | + type: 'http', |
| 218 | + scheme: 'bearer', |
| 219 | + }, |
| 220 | + }, |
| 221 | + }, |
| 222 | + security: [{ BearerAuth: [] }], |
| 223 | + }, |
| 224 | + ui: swagger.swaggerUI({ getSwaggerInitializerScript }), |
| 225 | + }), |
| 226 | + ); |
| 227 | + }; |
| 228 | + ``` |
| 229 | + |
| 230 | + Here is a preview together with a user service from [Using Schemas of Feathersjs v5 (dove)](/examples/generated_service_v5.md): |
| 231 | + |
| 232 | + |
| 233 | +[filename](../swagger-ui/index.html?url=../examples/authentication_v5_plugin.json ':include class=swui-preview') |
0 commit comments