Skip to content

Commit 8951518

Browse files
committed
Add doc/tests for bearer viewer
Signed-off-by: Alan Cha <[email protected]>
1 parent 47e2002 commit 8951518

File tree

6 files changed

+145
-69
lines changed

6 files changed

+145
-69
lines changed

packages/openapi-to-graphql/README.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,25 @@ The type and field names and enum values that OpenAPI-to-GraphQL generates may n
315315

316316
## Authentication
317317

318-
By default, OpenAPI-to-GraphQL will wrap API requests that need authentication in corresponding `viewers`, which allow the user to pass required credentials. OpenAPI-to-GraphQL currently supports viewers for basic authentication and API keys. For example, a query using an API key viewer is:
318+
By default, OpenAPI-to-GraphQL will wrap API requests that need authentication in corresponding `viewers`, which allow the user to pass required credentials. OpenAPI-to-GraphQL currently supports viewers for basic authentication, bearer tokens, and API keys. For example, a query using an API key viewer is:
319319

320-
```javascript
320+
```graphql
321+
{
322+
viewerBasicAuth (username: "user", password: "secret") {
323+
... // query for authenticated data here
324+
}
325+
}
326+
```
327+
328+
```graphql
329+
{
330+
viewerBearerAuth (token: "bearer_token_here") {
331+
... // query for authenticated data here
332+
}
333+
}
334+
```
335+
336+
```graphql
321337
{
322338
viewerApiKey (apiKey: "api_key_here") {
323339
... // query for authenticated data here
@@ -327,7 +343,7 @@ By default, OpenAPI-to-GraphQL will wrap API requests that need authentication i
327343

328344
OpenAPI-to-GraphQL uses dedicated viewers for mutations. For example, a mutation using a basic authentication viewer is:
329345

330-
```javascript
346+
```graphql
331347
mutation {
332348
mutationViewerBasic (username: "user", password: "secret") {
333349
... // mutate authenticated data here
@@ -337,7 +353,7 @@ mutation {
337353

338354
OpenAPI-to-GraphQL further provides `anyAuth` viewers (for queries and mutations), which allow the user to simultaneously provide information for multiple authentication mechanisms. `anyAuth` viewers allow OpenAPI-to-GraphQL to resolve nested queries and mutations that encompass API requests with different authentication mechanisms. For example, consider the following query:
339355

340-
```javascript
356+
```graphql
341357
{
342358
viewerAnyAuth (
343359
exampleApiKeyProtocol: {apiKey: "a1p2i3k4e5y"}

packages/openapi-to-graphql/test/authentication.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ test('Get patent using basic auth', () => {
5454
})
5555
})
5656

57+
test('Get patent using bearer token', () => {
58+
const query = `{
59+
viewerBearerAuth(token: "master-bearer-token") {
60+
patentWithId (patentId: "100") {
61+
patentId
62+
}
63+
}
64+
}`
65+
return graphql(createdSchema, query, null, {}).then((result) => {
66+
expect(result).toEqual({
67+
data: {
68+
viewerBearerAuth: {
69+
patentWithId: {
70+
patentId: '100'
71+
}
72+
}
73+
}
74+
})
75+
})
76+
})
77+
5778
test('Get patent using API key', () => {
5879
const query = `{
5980
viewerApiKey2 (apiKey: "abcdef") {

packages/openapi-to-graphql/test/example_api3_server.js

+48-28
Original file line numberDiff line numberDiff line change
@@ -91,55 +91,75 @@ function startServer(PORT) {
9191
}
9292

9393
const authMiddleware = (req, res, next) => {
94-
if (req.headers.authorization) {
95-
let encoded = req.headers.authorization.split(' ')[1]
96-
let decoded = new Buffer(encoded, 'base64').toString('utf8').split(':')
97-
98-
if (decoded.length === 2) {
99-
let credentials = {
100-
username: decoded[0],
101-
password: decoded[1]
102-
}
103-
for (let user in Auth) {
104-
if (
105-
Auth[user].username === credentials.username &&
106-
Auth[user].password === credentials.password
107-
) {
94+
if ('authorization' in req.headers) {
95+
const tokenizedAuth = req.headers.authorization.split(' ')
96+
97+
if (tokenizedAuth.length == 2) {
98+
const authType = tokenizedAuth[0]
99+
const authValue = tokenizedAuth[1]
100+
101+
if (authType == 'Basic') {
102+
// Decode username and password
103+
const decoded = new Buffer.from(authValue, 'base64').toString('utf8').split(':')
104+
105+
if (decoded.length === 2) {
106+
const credentials = {
107+
username: decoded[0],
108+
password: decoded[1]
109+
}
110+
111+
for (let user in Auth) {
112+
if (
113+
Auth[user].username === credentials.username &&
114+
Auth[user].password === credentials.password
115+
) {
116+
return next()
117+
}
118+
}
119+
} else {
120+
res.status(401).send({
121+
message: 'Basic Auth expects a single username and a single password'
122+
})
123+
}
124+
125+
} else if (authType == 'Bearer') {
126+
127+
if (authValue == 'master-bearer-token') {
108128
return next()
109129
}
110130
}
111-
res.status(401).send({
112-
message: 'Incorrect credentials'
113-
})
114-
} else {
115-
res.status(401).send({
116-
message: 'Basic Auth expects a single username and a single password'
117-
})
118131
}
132+
119133
} else if ('access_token' in req.headers) {
120134
for (let user in Auth) {
121135
if (Auth[user].accessToken === req.headers.access_token) {
122136
return next()
123137
}
124138
}
125-
res.status(401).send({
126-
message: 'Incorrect credentials'
127-
})
128-
return false
139+
140+
} else if ('cookie' in req.headers) {
141+
for (let user in Auth) {
142+
if (Auth[user].accessToken === req.headers.cookie.split('=')[1]) {
143+
return next()
144+
}
145+
}
146+
129147
} else if ('access_token' in req.query) {
130148
for (let user in Auth) {
131149
if (Auth[user].accessToken === req.query.access_token) {
132150
return next()
133151
}
134152
}
135-
res.status(401).send({
136-
message: 'Incorrect credentials'
137-
})
153+
138154
} else {
139155
res.status(401).send({
140156
message: 'Unknown/missing credentials'
141157
})
142158
}
159+
160+
res.status(401).send({
161+
message: 'Incorrect credentials'
162+
})
143163
}
144164

145165
app.get('/api/authors/:authorId', (req, res) => {

packages/openapi-to-graphql/test/example_api_server.js

+44-32
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
'use strict'
77

8+
const { printLocation } = require('graphql')
9+
810
let server // holds server object for shutdown
911

1012
/**
@@ -299,65 +301,75 @@ function startServer(PORT) {
299301
}
300302

301303
const authMiddleware = (req, res, next) => {
302-
if (req.headers.authorization) {
303-
const encoded = req.headers.authorization.split(' ')[1]
304-
const decoded = new Buffer(encoded, 'base64').toString('utf8').split(':')
305-
306-
if (decoded.length === 2) {
307-
const credentials = {
308-
username: decoded[0],
309-
password: decoded[1]
310-
}
311-
for (let user in Auth) {
312-
if (
313-
Auth[user].username === credentials.username &&
314-
Auth[user].password === credentials.password
315-
) {
304+
if ('authorization' in req.headers) {
305+
const tokenizedAuth = req.headers.authorization.split(' ')
306+
307+
if (tokenizedAuth.length == 2) {
308+
const authType = tokenizedAuth[0]
309+
const authValue = tokenizedAuth[1]
310+
311+
if (authType == 'Basic') {
312+
// Decode username and password
313+
const decoded = new Buffer.from(authValue, 'base64').toString('utf8').split(':')
314+
315+
if (decoded.length === 2) {
316+
const credentials = {
317+
username: decoded[0],
318+
password: decoded[1]
319+
}
320+
321+
for (let user in Auth) {
322+
if (
323+
Auth[user].username === credentials.username &&
324+
Auth[user].password === credentials.password
325+
) {
326+
return next()
327+
}
328+
}
329+
} else {
330+
res.status(401).send({
331+
message: 'Basic Auth expects a single username and a single password'
332+
})
333+
}
334+
335+
} else if (authType == 'Bearer') {
336+
337+
if (authValue == 'master-bearer-token') {
316338
return next()
317339
}
318340
}
319-
res.status(401).send({
320-
message: 'Incorrect credentials'
321-
})
322-
} else {
323-
res.status(401).send({
324-
message: 'Basic Auth expects a single username and a single password'
325-
})
326341
}
342+
327343
} else if ('access_token' in req.headers) {
328344
for (let user in Auth) {
329345
if (Auth[user].accessToken === req.headers.access_token) {
330346
return next()
331347
}
332348
}
333-
res.status(401).send({
334-
message: 'Incorrect credentials'
335-
})
336-
return false
349+
337350
} else if ('cookie' in req.headers) {
338351
for (let user in Auth) {
339352
if (Auth[user].accessToken === req.headers.cookie.split('=')[1]) {
340353
return next()
341354
}
342355
}
343-
res.status(401).send({
344-
message: 'Incorrect credentials'
345-
})
346-
return false
356+
347357
} else if ('access_token' in req.query) {
348358
for (let user in Auth) {
349359
if (Auth[user].accessToken === req.query.access_token) {
350360
return next()
351361
}
352362
}
353-
res.status(401).send({
354-
message: 'Incorrect credentials'
355-
})
363+
356364
} else {
357365
res.status(401).send({
358366
message: 'Unknown/missing credentials'
359367
})
360368
}
369+
370+
res.status(401).send({
371+
message: 'Incorrect credentials'
372+
})
361373
}
362374

363375
app.get('/api/users', (req, res) => {

packages/openapi-to-graphql/test/example_gql_server.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ const { graphqlHTTP } = require('express-graphql')
1111
const app = express()
1212
const openAPIToGraphQL = require('../dist/index')
1313

14-
// const oas = require('./fixtures/example_oas.json')
14+
const oas = require('./fixtures/example_oas.json')
1515
// const oas = require('./fixtures/example_oas2.json')
1616
// const oas = require('./fixtures/example_oas3.json')
17-
const oas = require('./fixtures/example_oas4.json')
17+
// const oas = require('./fixtures/example_oas4.json')
1818
// const oas = require('./fixtures/example_oas5.json')
1919
// const oas = require('./fixtures/example_oas6.json')
2020
// const oas = require('./fixtures/example_oas7.json')

packages/openapi-to-graphql/test/fixtures/example_oas.json

+10-3
Original file line numberDiff line numberDiff line change
@@ -765,14 +765,17 @@
765765
}
766766
},
767767
"security": [
768-
{
769-
"example_api_basic_protocol": []
770-
},
771768
{
772769
"example_api_key_protocol_2": []
773770
},
774771
{
775772
"example_api_key_protocol_3": []
773+
},
774+
{
775+
"example_api_basic_protocol": []
776+
},
777+
{
778+
"example_api_bearer_protocol": []
776779
}
777780
]
778781
}
@@ -1640,6 +1643,10 @@
16401643
"example_api_basic_protocol": {
16411644
"type": "http",
16421645
"scheme": "basic"
1646+
},
1647+
"example_api_bearer_protocol": {
1648+
"type": "http",
1649+
"scheme": "bearer"
16431650
}
16441651
},
16451652
"parameters": {

0 commit comments

Comments
 (0)