platform-samples icon indicating copy to clipboard operation
platform-samples copied to clipboard

Add query that lists SAML external identities for an Organization

Open osowskit opened this issue 7 years ago • 26 comments

Business Plan hosted customers with SAML would like a way to programmatically query information about a GitHub user account's SAML identity. The following is a GraphQL query that accomplishes this for an Organization.

  • [ ] Determine whether this is a standalone example for useful Business Plan hosted (SAML) queries or added under https://github.com/github/platform-samples/tree/master/graphql/queries
query {
  organization(login: "LOGIN") {
    samlIdentityProvider {
      ssoUrl
      externalIdentities(first: 100) {
        edges {
          node {
            guid
            samlIdentity {
              nameId
            }
            user {
              login
            }
          }
        }
      }
    }
  }
}

/cc @francisfuzz as you might be able to track down the author to see if they want to add this ☝️

osowskit avatar Feb 05 '18 22:02 osowskit

This query was super helpful for us as we're primarily using v3 and couldn't see a way to do this there. I found the token needs admin:org though which feels excessive for a read only query.

mikesimons avatar Jul 01 '19 14:07 mikesimons

This query was also super helpful for us - v3 provides their SCIM endpoint (https://developer.github.com/v3/scim/) which gets us close, but does not provide a true way to tie a GitHub identity to a SAML identity.

Using this query in v4 we are able to pull our user's verified domain email addresses and associate it to their github handle, making our notification process a lot easier.

AjkayAlan avatar Feb 20 '20 21:02 AjkayAlan

@AjkayAlan, I'm testing on the same where the email address for SAML authentication is different from github registered email address, can you please share us the query to trigger in GraphQL

kamaltejaaol avatar Jun 02 '20 02:06 kamaltejaaol

@kamaltejaaol Unfortunately my org policy does not allow me to share code easily, specifically code I developed for our organization.

What we ended up doing was using the query provided by @osowskit above to get the SAML nameId, which corresponded to our user's primary email address associated to their enterprise account (the same address we would send emails on). Additionally, the query above gets you the user login, which is the actual github login of the associated user.

From there, you can just make a key value pair list of github login to enterprise email address. Once you have that, you should be off to the races.

In our case, we had to revoke PAT and SSH keys over a specified age limit using the credential authorizations API (https://developer.github.com/v3/orgs/#list-credential-authorizations-for-an-organization). That returns the github login, which we then look up against the list of login/email kvp's. From there, we were able to notify the users in advance that they needed to rotate their credentials to avoid disruption.

AjkayAlan avatar Jun 02 '20 02:06 AjkayAlan

@AjkayAlan, i understand the corporate security policies, but thanks for giving the detailed explanation, i will try to work it out. Thanks again.

kamaltejaaol avatar Jun 02 '20 04:06 kamaltejaaol

Hi, @osowskit Thanks for this solution, really saved my day, however I am getting null with this query, not sure what I am missing here possibly? I have correct scope for the token and header stuff.

below is the return. { "data": { "organization": { "samlIdentityProvider": null } } }

gracevivi523 avatar Aug 06 '20 13:08 gracevivi523

@swinton @mtodd ☝️

osowskit avatar Aug 06 '20 13:08 osowskit

Thanks @osowskit .

@swinton @mtodd , I am still stuck on it, any help will be highly appreciated.

gracevivi523 avatar Aug 07 '20 03:08 gracevivi523

Just did a bit more research on the issue, could it be related to SCIM is not enabled?

gracevivi523 avatar Aug 07 '20 11:08 gracevivi523

I am experiencing the same {"data":{"organization":{"samlIdentityProvider":null}}} issue making requests with both

  • a PAT with admin:org and admin:enterprise permissions
  • as well as a Github App with fairly substantial permissions

So I'm wondering:

  1. My account is an org owner, but (I believe) only an enterprise member. Could this be the source of the issue?
  2. If it is, shouldn't at least enterprise.ownerInfo.samlIdentityProvider throw an error?
  3. More generally, what are the constraints and necessary permissions for this API?
  4. What are its the supported consumers, and do they have varied constraints?
  5. Are there known gotchas and caveats such as what @gracevivi523 proposed?

Also, this query has been added to the examples.

micimize avatar Dec 07 '20 20:12 micimize

What I've learned since the above:

  • is that when enterprise saml identity mapping is on, organization.samlIdentityProvider is not a view into the enterprise identity mapping, and there is no way to configure it as such
  • enterprise saml identities can only be queried by enterprise owners

micimize avatar Dec 11 '20 17:12 micimize

https://gist.github.com/gbaman/b3137e18c739e0cf98539bf4ec4366ad ... these details helped me to develop python code to get the saml identify value and generate report

kamaltejaaol avatar Dec 11 '20 20:12 kamaltejaaol

I also got {"data":{"organization":{"samlIdentityProvider":null}}} when querying the organization, that's because the SAML configuration was at the enterprise level, so to get that the following query helped.

{
  enterprise(slug: "Your enterprise here") {
    ownerInfo {
      samlIdentityProvider {
        externalIdentities(after: null, first: 100) {
          pageInfo {
            hasNextPage
            endCursor
          }
          edges {
            node {
              user {
                login
              }
              samlIdentity {
                nameId
              }
            }
          }
        }
      }
    }
  }
}

barakwei avatar Mar 09 '21 13:03 barakwei

For anyone interested in how to adapt the original query from the first comment to support pagination, after some playing around and reading the docs (I'm not too familiar with GraphQL, so this wasn't obvious to me), I got this (example below using the GitHub CLI, see also here):

gh api graphql --paginate -f query='
query($endCursor: String) {
  organization(login: "<name-of-org>") {
    samlIdentityProvider {
      ssoUrl,
      externalIdentities(first: 100, after: $endCursor) {
        edges {
          node {
            guid,
            samlIdentity {
              nameId
            }
            user {
              login
            }
          }
        }
        pageInfo{
          hasNextPage,
          endCursor
        }
      }
    }
  }
}
'

joehorsnell avatar Jul 04 '21 17:07 joehorsnell

for anyone who comes here looking for a way to find the organisational email for a particular user, it is:

query {
  user(login: "SOME-USER"){
    organizationVerifiedDomainEmails(login: "SOME-ORG")
  }
}

alex-mozejko avatar Sep 03 '21 07:09 alex-mozejko

Is there no way to get this information with a REST API endpoint?

genio avatar Apr 15 '22 14:04 genio

So I wanted to find the GH username for a specific SAML email address and didn't want to have to paginate and loop through the results so this worked for me:

organization(login: "org") {
  samlIdentityProvider {
    externalIdentities(first: 100, userName: "[email protected]") {
      edges {
        node {
          user {
            login
          }
          samlIdentity {
            nameId
          }
        }
      }
    }
  }
}

threesquared avatar May 27 '22 15:05 threesquared

Thanks all - this helped me out.

For anyone working with c# who gets here, here's a gist https://gist.github.com/dylan-asos/091f2b8e6a865538f061f7554fc03566 - give it an email, it'll give you the matching username/login.

I'm being overly verbose to show some of the moving parts, you could switch out some of that with parsing libs of your choice.

dylan-asos avatar Aug 15 '22 14:08 dylan-asos

I'm trying this but we have SAML enabled at Enterprise level and when we try these or similar queries I get this:

The Organization's SAML identity provider is disabled when an Enterprise SAML identity provider is available.

I can't find any similar option to get this information at the enterprise level. Any ideas on how to get that info?

EdEastman avatar Sep 12 '22 15:09 EdEastman

@EdEastman see my comment above

barakwei avatar Sep 12 '22 17:09 barakwei

Gah, sorry, now I'm the guy that didn't read the thread :( oh well hopefully at least that error message will be indexed now...many thanks @barakwei - that works perfectly

EdEastman avatar Sep 12 '22 19:09 EdEastman

for anyone who comes here looking for a way to find the organisational email for a particular user, it is:

query {
  user(login: "SOME-USER"){
    organizationVerifiedDomainEmails(login: "SOME-ORG")
  }
}

Thanks ,Here is the query with variables

query($user: String!, $org:String!) { user(login: $user){ organizationVerifiedDomainEmails(login: $org) } }

{ "user": "SOME-USER", "org": "SOME-ORG" }

DushanthaS avatar Mar 29 '23 15:03 DushanthaS

Hello, With enterprise-level SAML I get "ownerInfo": null for the following query:

{
  enterprise(slug: "Your enterprise here") {
    ownerInfo {
      samlIdentityProvider {
        id
      }
    }
}

I still can see the sso email through web interface though. Please help

mikheyevav avatar Nov 29 '23 15:11 mikheyevav

Has anyone got this to work on enterprise server? I can get it to work on cloud but not server (self-hosted). I'm just getting:

{"data":{"enterprise":{"ownerInfo":{"samlIdentityProvider":null}}}}

dmtri35 avatar Apr 01 '24 19:04 dmtri35