Access linked SAML identity via the GitHub API - github

I'd like to get a mapping between GitHub logins and emails in my organization using the GitHub API (any version).
I can get the emails on organization members' accounts with this GraphQL query:
query {
organization(login:"myorg"){
members(first:100) {
nodes {
login
name
email
}
}
}
}
But this isn't the email I'm after. I really want the email on the "Linked SSO identity", which I get to from my organization page by clicking this link:
When I click this link, the desired email is listed in several places on https://github.com/orgs/myorg/people/danvk/sso.
Is it possible to access this SSO-linked email via any version of the GitHub API?

Organisation Level SAML
You can access this information for accounts provisioned via SCIM*.
query {
organization(login: "LOGIN") {
samlIdentityProvider {
ssoUrl
externalIdentities(first: 100) {
edges {
node {
guid
samlIdentity {
nameId
}
user {
login
}
}
}
}
}
}
}
[authored by a member of GitHub's support staff] and samples available here.
I haven't verified if accounts that have linked SAML accounts outside of SCIM would work using this query.
Enterprise Level SAML
If your IdP's configured at the enterprise level, run instead:
{
enterprise(slug: "MYENTERPRISENAME") {
ownerInfo {
samlIdentityProvider {
externalIdentities(after: null, first: 100) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
user {
login
}
samlIdentity {
nameId
}
}
}
}
}
}
}
}
Additional Info
These GraphQL queries can be run via the GitHub CLI (download here).
Permissions are provided by a personal access token (PAT). You can set this up at https://github.com/settings/tokens.
If querying the org, you'll need to assign your PAT the admin:org right. You'll also need to authorise it for each org against which you intend to use it (via the Configure SSO option next to the PAT.
If querying the enterprise, you'll need to assign your PAT the admin:enterprise right.
To authenticate create an environment variable, GH_TOKEN, and set its value to the token's value (if you didn't note this when creating the token, you'll have to drop and recreate the token to get a fresh value).
Examples of how to use the gh cli to run graphql (and other API) queries can be found here: https://cli.github.com/manual/gh_api

this worked for what i needed:
query {
user(login: "SOME-USER"){
organizationVerifiedDomainEmails(login: "SOME-ORG")
}
}

Related

GitHub API and Email Adddresses

Im trying to pull the email addresses for all users within my org.
My GraphQL query looks like this:
{
organization(login: "####") {
membersWithRole(first: 100) {
totalCount
edges {
node {
login
name
email
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
However, it only shows the email if the user has made it publicly shown. The reason I need this is to remove users from my org that have left/cancelled.
Thanks,
it only shows the email if the user has made it publicly shown.
Yes, which means that private emails are not to be queried or, as explained here:
some users don't have an e-mail address defined in github.com/settings/profile and that causes the email field in the API response to be blank.
As asked before, using email alone won't work, since private emails would not be part of that kind of queries.
That can give you a User node is null if email is private or unset.
An other approach would be needed in your case, like, for instance, Get last activity for a user in an organisation GitHub Ecosystem.

How do I enable auto-merge on a github pull request via the Rest API

I have permission, the repo allows it. I create a bunch of PRs using a cli tool and then I have to go open N tabs and double click the Enable Auto-Merge -> Confirm process for each one.
Does the API offer an issue/pr modify method to set this attribute automatically without resorting to the UI?
It seems that at the moment it's not possible to do it via Rest API, but you can use GraphQL API mutation enablePullRequestAutoMerge instead.
I solved it like this:
Request POST to https://api.github.com/graphql to get pullRequestID value
body:
query MyQuery {
repository(name: "repo-example", owner: "org-example) {
pullRequest(number: 49) {
id
}
}
}
With pullRequest ID make a mutation:
Request POST to https://api.github.com/graphql
mutation MyMutation {
enablePullRequestAutoMerge(input: {pullRequestId: "$pullRequestID", mergeMethod: MERGE}) {
clientMutationId
}
}

Add member to Azure DevOps team

I've able to get team or team member but I could not find away to add user to the team. Is there RESt_API, command line, or API that I could add user to the team using domain name "domain\user". Please advise. Great appreciate
Best Regards,
If you use Azure DevOps Service (https://dev.azure.com/xxxx), you could use Members - Add REST API.
If you use Azure DevOps Server, the REST API to add members to projects and team is not documented. As a workaround, we can track this rest api by pressing F12 in browser then select Network.
Sample:
POST http://TFS2019:8080/tfs/{Collection}/{project}/_api/_identity/AddIdentities?api-version=5.0
Request Body:
{
"newUsersJson": "[]",
"existingUsersJson": "[\"55b98726-c6f5-48d2-976b-xxxxxx\"]",
"groupsToJoinJson": "[\"7283653f-54b2-4ebf-86c3-xxxxxxx\"]",
"aadGroupsJson": "[]"
}
However as we can see we can only use the user and team/group GUID in the request json body. For the specific team/groups we can use the REST APIs Projects and teams to get their GUID.
For the user, actually it's used the TeamFoundationId, the unique TeamFoundationId is automatically generated when a user is added to Azure DevOps Server. We cannot generate the ID with external tools.
So, to use that REST API, we need to get the TeamFoundationId of the specific user which you want to add it to the projects/teams.
Currently, no REST API to list TeamFoundationId of the users in Azure DevOps Server 2019, however we can get it with Client API:
Below sample for your reference to get the TeamFoundationId of a specific user: (It will also export the user list with their TeamFoundationId to userlist.txt)
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using System.Linq;
using System.IO;
namespace Getuserlist
{
class Program
{
static void Main(string[] args)
{
TfsConfigurationServer tcs = new TfsConfigurationServer(new Uri("https://wsicads2019"));
IIdentityManagementService ims = tcs.GetService<IIdentityManagementService>();
TeamFoundationIdentity tfi = ims.ReadIdentity(IdentitySearchFactor.AccountName, "[DefaultCollection]\\Project Collection Valid Users", MembershipQuery.Expanded, ReadIdentityOptions.None);
TeamFoundationIdentity[] ids = ims.ReadIdentities(tfi.Members, MembershipQuery.None, ReadIdentityOptions.None);
using (StreamWriter file = new StreamWriter("userlist.txt"))
foreach (TeamFoundationIdentity id in ids)
{
if (id.Descriptor.IdentityType == "System.Security.Principal.WindowsIdentity" && id.UniqueName == "Domain\\User")
{ Console.WriteLine("[{0},{1}]", id.UniqueName, id.TeamFoundationId); }
file.WriteLine("[{0},{1}]", id.UniqueName, id.TeamFoundationId);
}
var count = ids.Count(x => ids.Contains(x));
Console.WriteLine(count);
Console.ReadLine();
}
}
}

How to Identify caller when grant_type is client_credentials?

I have ASP.NET Web application and I am using IdentityServer3 for user authentication. Our customers login to web application using userid/password.
Now I have one more Web API and some of our customers need to call this web api from their applications. (server to server communication). So based on this, in identityserver i did the following
1> Created a new scope name api
2> Created a new client for Web API and configured with allowed scope api and offline_access
3> Set flow to ClientCredentials
4> Set AccessTokenType to Jwt
5> For each customer i created different secret key
Now our customers can get access token at connect/token endpoint and then make call to API using the access token. The API validates the token with IdentityServer, and then returns the result. All good till here.
However, in API project i also need to identify the customer aka caller. Based on customer i need to do some logic
public class ResourcesController : ApiController
{
public IHttpActionResult Get()
{
var caller = User as ClaimsPrincipal;
// need to identify caller here
return Json(new
{
message = "OK",
});
}
}
(One option i can think of is taking customer id is as part of API url. Something like http://api.domain.com/v1/customerid/resources)
Is there anyway to make a use of IdentityServer to identify customer?
I've actually had a similar need some time ago. For the simplest solution, you should be able to assign a custom claim to each of the Identity Server client that you have created for your customers.
AlwaysSendClientClaims = true,
Claims = new List<Claim>()
{
new Claim("CustomerId", "0121021")
}
These client claims will then be included in the access token and therefore available to you in your backend.
public class ResourcesController : ApiController
{
public IHttpActionResult Get()
{
var caller = User as ClaimsPrincipal;
// need to identify caller here
var customerId = caller?.Claims.Where(p => p.Type.Equals("CustomerId")).First().Value;
// need to identify caller here
return Json(new
{
message = "OK",
});
}
}

Jira 5.2 Seraph SSO Login behind reverse proxy

Since a few days I'm trying to enable SSO for Jira 5.2 and figured out, that the help page from Jira is outdated.
Each example uses an old version of atlassian-seraph (Jira 5.2 uses 2.6.0).
Goal:
I want to get automatically logged in into Jira if I'm logged in into Webseal (reverse proxy).
Background:
Jira is behind a reverse proxy (see picture).
This proxy authentificatates the user and holds the session.
If I'm logged in I want to be logged in in Jira, too
The only information provided is the user name
Question:
How to write a custom login module that reads the username from http_header and authentificates the user?
Links:
https://confluence.atlassian.com/display/DEV/Single+Sign-on+Integration+with+JIRA+and+Confluence
http://docs.atlassian.com/atlassian-seraph/latest/sso.html
https://answers.atlassian.com/questions/23245/how-to-integrate-jira-with-my-company-s-sso
In the end i figured it out by myself:
You need a custom authenticator
public class MyCustomAuthenticator extends DefaultAuthenticator {
protected boolean authenticate(Principal user, String password)
throws AuthenticatorException {
return true;
}
protected Principal getUser(String username) {
return getCrowdService().getUser(username);
}
private CrowdService getCrowdService() {
return (CrowdService)ComponentManager.getComponent(CrowdService.class);
}
}
Add the MyCustomAuthenticator to seraph-config.xml
<authenticator class="com.company.jira.MyCustomAuthenticator"/>
Write a Custom Filter to set the user name from http-header
public class CustomFilter extends PasswordBasedLoginFilter {
#Override
protected UserPasswordPair extractUserPasswordPair(
HttpServletRequest request) {
String username = request.getHeader("iv-header");
if (username != null && username.trim().length() != 0) {
return new PasswordBasedLoginFilter.UserPasswordPair(
username, "DUMMY", false);
}
return null;
}
}
Replace the filter within the web.xml
<filter>
<filter-name>login</filter-name>
<filter-class>com.company.jira.CustomFilter</filter-class>
</filter>
These jar's are needed for Jira 5.2
embedded-crowd-api-2.6.2
jira-core-5.2.1
atlassian-seraph-2.6.0
I am not familiar with Jira authentication, but I do understand well the SiteMinder/ WebSeal authentication.
Both systems authenticate user and send the user name in an HTTP header.
The name of HTTP header can be configured. Also, they can send additional user properties, like the user email in the additional HTTP headers.
TO authenticate a user behind SiteMinder/ WebSeal it is just required to take the HTTP header and to create an application session using the user name from the header.
You definitely can solve it in Jira. You have 2 options:
To use already created SiteMinder authenticator:
https://confluence.atlassian.com/display/DEV/SiteMinder+Custom+Seraph+Authenticator+for+Confluence
The problem that I did not find how to configure the HTTP header name for the user name header. It assumes that the header name is uid
You need to configure the header uid in WebSeal or try to obtain sources and make the header name configurable.
Implement your own authenticator according to your link:
http://docs.atlassian.com/atlassian-seraph/latest/sso.html
Obtain the user name using the code
httpServletRequest.getHeader(userNameHeaderName);