Skip to content

Commit

Permalink
feat: allow injecting an authorization middleware (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
billiegoose authored May 29, 2019
1 parent fc07a28 commit 476b3e2
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 6 deletions.
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,73 @@ Kill the process with the PID specified in `$PWD/cors-proxy.pid`:
cors-proxy stop
```

## Configuration
### CLI configuration

Environment variables:
- `PORT` the port to listen to (if run with `npm start`)
- `ALLOW_ORIGIN` the value for the 'Access-Control-Allow-Origin' CORS header
- `INSECURE_HTTP_ORIGINS` comma separated list of origins for which HTTP should be used instead of HTTPS (added to make developing against locally running git servers easier)


## Middleware usage

You can also use the `cors-proxy` as a middleware in your own server.

```js
const express = require('express')
const corsProxy = require('@isomorphic-git/cors-proxy/middleware.js')

const app = express()
const options = {}

app.use(corsProxy(options))

```

### Middleware configuration

*The middleware doesn't use the environment variables.* The options object supports the following properties:

- `origin`: _string_. The value for the 'Access-Control-Allow-Origin' CORS header
- `insecure_origins`: _string[]_. Array of origins for which HTTP should be used instead of HTTPS (added to make developing against locally running git servers easier)
- `authorization`: _(req, res, next) => void_. A middleware function you can use to handle custom authorization. Is run after filtering for git-like requests and handling CORS but before the request is proxied.

_Example:_
```ts
app.use(
corsProxy({
authorization: (req: Request, res: Response, next: NextFunction) => {
// proxied git HTTP requests already use the Authorization header for git credentials,
// so their [Company] credentials are inserted in the X-Authorization header instead.
if (getAuthorizedUser(req, 'X-Authorization')) {
return next();
} else {
return res.status(401).send("Unable to authenticate you with [Company]'s git proxy");
}
},
})
);

// Only requests with a valid JSON Web Token will be proxied
function getAuthorizedUser(req: Request, header: string = 'Authorization') {
const Authorization = req.get(header);

if (Authorization) {
const token = Authorization.replace('Bearer ', '');
try {
const verifiedToken = verify(token, env.APP_SECRET) as IToken;
if (verifiedToken) {
return {
id: verifiedToken.userId,
};
}
} catch (e) {
// noop
}
}
}
```

## License

This work is released under [The MIT License](https://opensource.org/licenses/MIT)
39 changes: 34 additions & 5 deletions middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const allowHeaders = [
'range',
'referer',
'user-agent',
'x-authorization',
'x-http-method-override',
'x-requested-with',
]
Expand Down Expand Up @@ -58,19 +59,47 @@ const filter = (predicate, middleware) => {
return corsProxyMiddleware
}

module.exports = ({ origin, insecure_origins = [] } = {}) => {
const compose = (...handlers) => {
const composeTwo = (handler1, handler2) => {
function composed (req, res, next) {
handler1(req, res, (err) => {
if (err) {
return next(err)
} else {
return handler2(req, res, next)
}
})
}
return composed
}
let result = handlers.pop()
while(handlers.length) {
result = composeTwo(handlers.pop(), result)
}
return result
}

function noop (_req, _res, next) {
next()
}

module.exports = ({ origin, insecure_origins = [], authorization = noop } = {}) => {
function predicate (req) {
let u = url.parse(req.url, true)
// Not a git request, skip
return allow(req, u)
}
function middleware (req, res) {
let u = url.parse(req.url, true)

function sendCorsOK (req, res, next) {
// Handle CORS preflight request
if (req.method === 'OPTIONS') {
return send(res, 200, '')
} else {
next()
}
}
function middleware (req, res) {
let u = url.parse(req.url, true)


let headers = {}
for (let h of allowHeaders) {
Expand Down Expand Up @@ -110,5 +139,5 @@ module.exports = ({ origin, insecure_origins = [] } = {}) => {
allowCredentials: false,
origin
})
return filter(predicate, cors(middleware))
return filter(predicate, cors(compose(sendCorsOK, authorization, middleware)))
}

0 comments on commit 476b3e2

Please sign in to comment.