module.exports = authenticationBeforeRequest const btoa = require('btoa-lite') const withAuthorizationPrefix = require('./with-authorization-prefix') function authenticationBeforeRequest (state, options) { if (typeof state.auth === 'string') { options.headers['authorization'] = withAuthorizationPrefix(state.auth) // https://developer.github.com/v3/previews/#integrations if (/^bearer /i.test(state.auth) && !/machine-man/.test(options.headers['accept'])) { const acceptHeaders = options.headers['accept'].split(',') .concat('application/vnd.github.machine-man-preview+json') options.headers['accept'] = acceptHeaders.filter(Boolean).join(',') } return } if (state.auth.username) { const hash = btoa(`${state.auth.username}:${state.auth.password}`) options.headers['authorization'] = `Basic ${hash}` if (state.otp) { options.headers['x-github-otp'] = state.otp } return } if (state.auth.clientId) { // There is a special case for OAuth applications, when `clientId` and `clientSecret` is passed as // Basic Authorization instead of query parameters. The only routes where that applies share the same // URL though: `/applications/:client_id/tokens/:access_token`. // // 1. [Check an authorization](https://developer.github.com/v3/oauth_authorizations/#check-an-authorization) // 2. [Reset an authorization](https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization) // 3. [Revoke an authorization for an application](https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application) // // We identify by checking the URL. It must merge both "/applications/:client_id/tokens/:access_token" // as well as "/applications/123/tokens/token456" if (/\/applications\/:?[\w_]+\/tokens\/:?[\w_]+($|\?)/.test(options.url)) { const hash = btoa(`${state.auth.clientId}:${state.auth.clientSecret}`) options.headers['authorization'] = `Basic ${hash}` return } options.url += options.url.indexOf('?') === -1 ? '?' : '&' options.url += `client_id=${state.auth.clientId}&client_secret=${state.auth.clientSecret}` return } return Promise.resolve() .then(() => { return state.auth() }) .then((authorization) => { options.headers['authorization'] = withAuthorizationPrefix(authorization) }) }