I am working on an azure devops extension that adds a new hub to the UI. The javascript code in the extension passes on both the app token (retrieved via SDK.getAppToken()
) and the access token (retrieved via SDK.getAccessToken()
) to the backend. I am trying to use the access token to retrieve the group memberships of the signed in user using the Memberships - List API. However I am getting a 401 unauthorized.
I am doing this experiment in Postman. So, first I retrieved both app token and access token using the chrome developer tools when the extension was sending the request to backend. And then I used the access token in Postman as a bearer token.
GET https://vssps.dev.azure.com/{organization}/_apis/graph/Memberships/{my subject descriptor}?api-version=6.0-preview.1
This returns a 401.
<div class="title">401 - Uh-oh, you do not have access.</div>
<div class="details">The request requires authentication.</div>
I know the access token is correct because I was able to use it successfully to access:
GET https://vssps.dev.azure.com/{organization}/_apis/connectionData
And I know the subject descriptor is correct because I am using the value that was returned by that connectionData API above.
Any idea if I am making an obvious mistake? My main goal is to be able to check if the user using my extension belongs to a specific group (that is, I don't need a list of their memberships, but just if they belong to this one group that I care about). I also tried the Check Membership existence API with the same 401 result.
I finally figured it out and leaving it here for others' benefit in future.
TL;DR: I needed to add vso.graph scope to my extension's manifest's scope property.
The API reference for membership APIs mention what scopes are needed for each call.
Scopes
Name Description
vso.graph Grants the ability to read user, group, scope and group membership information
Scopes needed by an extension can be defined in its manifest as documented here. In my manifest, I didn't have the scope property at all, so it defaulted to a scope of vso.extension.default which is not sufficient to access membership APIs. So I added below lines:
"scopes": [
"vso.graph"
],
And then I re-published the extension. On the other side, the organization side, where the extension was installed, I had to accept the additional permissions that the extension now demands. This doesn't happen automatically. It's explained here: Changing scope of published extension.