Skip to content

Commit

Permalink
🔧 Fix Check For When User Does Not Have a GitHub Identity
Browse files Browse the repository at this point in the history
  • Loading branch information
connormaglynn committed Dec 5, 2024
1 parent d94a63d commit dc9e6d3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 26 deletions.
49 changes: 25 additions & 24 deletions auth0-actions/allow-github-organisations-and-map-saml.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,38 @@ exports.onExecutePostLogin = async (event, api) => {
}

const identity = event.user.identities.find(identity => identity.provider.toLowerCase() === 'github')
if (!identity) {
return api.access.deny('User does not have a GitHub identity')
}

if (identity) {
// Get user's GitHub access token from Auth0 Management API, to find organisations/teams for the user
const githubIdentity = await getIdpAccessToken(AUTH0_MANAGEMENT_CLIENT_ID, AUTH0_MANAGEMENT_CLIENT_SECRET, AUTH0_TENANT_DOMAIN, event.user.user_id).catch(error => api.access.deny(`Error calling Auth0 Management API: ${error}`))
// Get user's GitHub access token from Auth0 Management API, to find organisations/teams for the user
const githubIdentity = await getIdpAccessToken(AUTH0_MANAGEMENT_CLIENT_ID, AUTH0_MANAGEMENT_CLIENT_SECRET, AUTH0_TENANT_DOMAIN, event.user.user_id).catch(error => api.access.deny(`Error calling Auth0 Management API: ${error}`))

const octokit = new Octokit({ auth: githubIdentity.access_token })
const octokit = new Octokit({ auth: githubIdentity.access_token })

// Get the authenticated user's GitHub organisation memberships
const userOrganisations = await octokit.request('GET /user/orgs').catch(error => api.access.deny(`Error retrieving orgs from GitHub: ${error}`))
// Get the authenticated user's GitHub organisation memberships
const userOrganisations = await octokit.request('GET /user/orgs').catch(error => api.access.deny(`Error retrieving orgs from GitHub: ${error}`))

// Check if a user is part of an allowed organisation
const authorised = userOrganisations.data.map(organisation => organisation.login).some(organisation => allowedOrganisations.includes(organisation))
// Check if a user is part of an allowed organisation
const authorised = userOrganisations.data.map(organisation => organisation.login).some(organisation => allowedOrganisations.includes(organisation))

if (authorised) {
const allowedDomain = JSON.parse(event.secrets.ALLOWED_DOMAINS)
if (authorised) {
const allowedDomain = JSON.parse(event.secrets.ALLOWED_DOMAINS)

// AWS requires the SAML nameID format to be an email address, which must
// exactly match an existing user in AWS SSO:
// https://docs.aws.amazon.com/singlesignon/latest/userguide/troubleshooting.html
api.samlResponse.setAttribute('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', `${event.user.nickname}${allowedDomain}`)
api.samlResponse.setAttribute('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', `${event.user.nickname}${allowedDomain}`)
// AWS requires the SAML nameID format to be an email address, which must
// exactly match an existing user in AWS SSO:
// https://docs.aws.amazon.com/singlesignon/latest/userguide/troubleshooting.html
api.samlResponse.setAttribute('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', `${event.user.nickname}${allowedDomain}`)
api.samlResponse.setAttribute('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', `${event.user.nickname}${allowedDomain}`)

// Set SAML attribute for the user's GitHub team memberships
// Ensure character limit stays inside documented constraint
const userTeamsResponse = await octokit.request('GET /user/teams').catch(error => api.access.deny(`Error retrieving teams from GitHub: ${error}`))
const userTeamSlugs = userTeamsResponse.data.map(team => team.slug)
const joinTeamSlugs = userTeamSlugs.join(':')
const trimTeamSlugs = joinTeamSlugs.slice(0, 256)
api.samlResponse.setAttribute('https://aws.amazon.com/SAML/Attributes/AccessControl:github_team', `${trimTeamSlugs}`)
// Set SAML attribute for the user's GitHub team memberships
// Ensure character limit stays inside documented constraint
const userTeamsResponse = await octokit.request('GET /user/teams').catch(error => api.access.deny(`Error retrieving teams from GitHub: ${error}`))
const userTeamSlugs = userTeamsResponse.data.map(team => team.slug)
const joinTeamSlugs = userTeamSlugs.join(':')
const trimTeamSlugs = joinTeamSlugs.slice(0, 256)
api.samlResponse.setAttribute('https://aws.amazon.com/SAML/Attributes/AccessControl:github_team', `${trimTeamSlugs}`)

return // this empty return is required by auth0 to continue to the next action
}
return // this empty return is required by auth0 to continue to the next action
}
}
4 changes: 2 additions & 2 deletions auth0-actions/allow-github-organisations-and-map-saml.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ describe('onExecutePostLogin', () => {
expect(mockApi.samlResponse.setAttribute).not.toHaveBeenCalled()
})

test('access denied given user identity provider is not `github`', async () => {
test('access denied given user does not have a GitHub identity', async () => {
mockEvent = {
...mockEvent,
user: { identities: [{ provider: 'NOT_GITHUB' }], nickname: 'test-user' },
}

await onExecutePostLogin(mockEvent, mockApi)

expect(mockApi.access.deny).toHaveBeenCalledWith('Access denied.')
expect(mockApi.access.deny).toHaveBeenCalledWith('User does not have a GitHub identity')
expect(mockApi.samlResponse.setAttribute).not.toHaveBeenCalled()
})
})

0 comments on commit dc9e6d3

Please sign in to comment.