TFS REST API: How to "Make requests on behalf of others"? - rest

I want my VSTS extension (installed on-prem TFS2015.3) to be able to do specific requests on behalf of a admin/service account ("Make requests on behalf of others")
Background: I manipulate (WorkItem) Process Template, specifically the GLOBALWORKFLOW (only on team-project level) in my extensions typescript, but the user of the extension in Web Access is NOT a project-admin so he is not allowed to use the function updateWorkItemTypeDefinition() - Non-Project-Admins get "Access denied" even if I gave that custom group every permission available ("Edit project-level-information" permissions for project-level GLOBALWORKFLOWs? Still didn't work for custom groups, only for Project Admin Accounts).
It seems I'm forced to impersonate a project admin /service account which is allowed to change the global workflow in the project
How do I impersonate in extension typescript code on-prem TFS and REST (1. not .NET and 2. without changing to basic auth, saw that solution already somewhere else - but I'm very sure I cannot request that change in my organization)
Thanks for your help

You can impersonate user through vsts-node-api.
There are many function to impersonate user, such as Basic, NTLM, PWA (VSTS) etc..., you can check these function here.
import * as vm from 'vso-node-api';
// your collection url
var collectionUrl = "XXX";
let authHandler = vm.getNtlmHandler("[user name]","[password]","[workstation optional]","[domain optional]");
var connect = new vm.WebApi(collectionUrl, authHandler);
There is the sample that you could refer to.

Related

What and where are the required permissions to republish existing VS Code extension?

A year ago I published a Visual Studio Code extension with vsce. I wish to publish an update, but lost the old token. I created a new one, but have not been able to find the right combination of permissions to republish.
Without supplying a new token, I get:
> vsce publish
ERROR Failed request: (401)
Using the new token with Full access scope on All accessible organizations or with the documented Marketplace scopes, I get:
> vsce publish -p newtoken
ERROR Access Denied: xxx needs the following permission(s) on the resource /aaa/bbb to perform this action: Make changes to, share, or view certificate of an existing extension
What have I missed in setting up permissions to republish?
Arg. I should have known once I took the time to post a question I'd figure out the problem. Back story: After adopting Azure AD, there was great confusion among developers here between Office 365 accounts and Microsoft accounts--because we had been advised to use the same email address for both.
Long story short, the problem was I was attempting to publish using a token from my Office 365 account, when the extension was originally published under my Microsoft account. It was long enough ago that I didn't remember that. I also gave my O365 account access to the organization owned by my Microsoft account, so I could conveniently access various resources with either one.
I created a new token under my Microsoft account, and boom, publish succeeded.

Call Microsoft Graph API - App only unauthorized error

I am trying to make request to the Graph API using a service with no UI. I downloaded the following sample code and followed the instructions: https://blog.kloud.com.au/2015/12/14/implementing-application-with-o365-graph-api-in-app-only-mode/
I successfully get an Access Token, but when using it to make a request to get organization information (required Read Directory Data access), I get 403 Unauthorized.
I have registered my app in Azure AD (where I am a co-administrator).
I have specified Microsoft Graph in the 'permissions to other applications' section, and given Read Directory Data access.
Interestingly there is a note below saying 'You are authorized to select only delegated permissions which have personal scope'. Even though I clearly did. Why? I suspect this is the source of my problem.
Likewise I have checked my demo app against these instructions: https://graph.microsoft.io/en-us/docs/authorization/app_only, but it makes no mention of what role in Azure you need to have.
in this SO post's answer, there is mention of still needing to Consent. I haven't found any documentation about this.
You are authorized to select only delegated permissions which have personal scope
This issue is caused that the app is created by none admin and when they visit the portal then will see this message.
To grant the app-only permission to the application, we need to be the administrator of the tenant. It is different with the co-administrator. To user the Client Credential flow, I suggest that you contact the admin of the tenant to create an application for you. And if you were just for testing purpose, you can create a free tenant and register the application yourself.
Update
We need the assign the Global administrator director role as figure below to make the application works for the client credential flow:

Get Azure subscription details of client

I want to get details of Azure Subscription of my client. But I do not want to ask for special permission from client.
What I need is the bare minimum things from my client so that I can login from powershell or rest api and read status of runbook jobs.
If i login from admin account of the subscription than I can easily get those details. But you understand it is not possible to have admin account credential of my client.
Please suggest some workaround.
What you need to do is create a user in Azure Active Directory and grant that user specific rights using either the Azure Portal or PowerShell\Cli\SDK.
Say read all, or read properties of desired automation account. If you would want like a super minumim, you would need to create a custom role first.
https://azure.microsoft.com/en-us/documentation/articles/role-based-access-control-custom-roles/
If your client placed specific resources within a Resource Group, they may grant you permissions on just that Resource Group (including read-only permissions). This would allow you to have access to needed resources, without having access to other areas of their subscription.

Authenticating (Team Foundation Server) with impersonalization

I have found how to authenticate to TFS from my app with a given username/password.
I'd like to use the REST services.
public static void BasicAuthRestSample()
{
// Create instance of VssConnection using basic auth credentials.
// For security, ensure you are connecting to an https server, since credentials get sent in plain text.
VssConnection connection = new VssConnection(new Uri(collectionUri), new VssCredentials(new WindowsCredential(new NetworkCredential(username, password))));
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
List<QueryHierarchyItem> items = witClient.GetQueriesAsync(teamProjectName).Result;
}
This solution is working fine, but if i create a new workitem, that is created by "username".
But i want to create workitems by impersonalized users, so i want to see "seconduser" as the creator if i look at the workitem in TFS.
I was googling a lot but can't find an example....
Update for VSTS:
After trying to implement i have found this:
"For security reasons (and compliance and a number of other reasons), the impersonation header isn't supported on Visual Studio Online"
A strange thing is that the error message currently misleading, it tells me that I need the special permission while the whole impersonation feature is actually disabled in VSTS.
According to REST API Reference for VS Team Services and TFS, there is no REST API similar to TFS Impersonation right now. As the .net api still works with VSTS for most features (not support vNext build, etc), you can take the .net api as an alternative.
You should use the TfsTeamProjectCollection constructor accepting an IdentityDescriptor.
You can find the full explanation in Introducing TFS Impersonation.
Snippet from the post
// Get the TFS Identity Management Service
IIdentityManagementService identityManagementService =
currentUserCollection.GetService<IIdentityManagementService>();
// Look up the user that we want to impersonate
TeamFoundationIdentity identity = identityManagementService.ReadIdentity(
IdentitySearchFactor.AccountName, username, MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedCollection =
new TfsTeamProjectCollection(currentUserCollection.Uri, identity.Descriptor);

Using O365 REST APIs can I then use Discovery APIs to find user's 0365 SharePoint servers via Oauth2?

we've seen this SO question already and using the O365 REST API we have a working Oauth2 workflow that authenticates an O365 user and returns an access token. Our question is: Once we have an access token for a user, how can we discover the user's SharePoint servers (and associated endpoints) without knowing the authenticated user's O365 SharePoint server URLs ahead of time?
Our application uses Oauth2 workflows to access data on behalf of users from GitHub, DropBox, Google Docs and other services, and typically once user permission has been granted and we have an access token there is a straightforward way of querying/retrieving the resources for the user via the access token.
Once we have an access token, we're calling the O365 Discovery Services. If I'm reading the docs correctly, we should be getting back ServiceInfo entries on a request to the O365 /Services endpoint with an access token, like this:
https://contoso-my.sharepoint.com/personal/alexd_contoso_com
https://contoso-my.sharepoint.com
But at present we only get back O365 File and Contact ServiceInfo entries, even though in the Azure Portal when we created our app we specified Office 365 SharePoint Online Delegated Permission ('Read List').
If there are different O365 endpoints we should be hitting once we have an access token in order to discover a user's SharePoint servers, or if we're using the Discovery Services wrong, please provide a few pointers -- We want to solve this problem in a generic fashion based on Oauth2 workflow and don't want to prompt the user for things like O365 SharePoint Server URLs.
Lastly I'd mention that we're accessing this info in a purely RESTful fashion and we have no Windows-specific dependencies (in fact we're building things on the JVM) so a workable solution for us must not depend on Windows-only APIs or platforms.