Here's what I have been trying to do:
- Created an app under AAD. Added the user_impersonation API permission to it. Created a secret and noted down the App ID
- Been trying to use this python code to generate a new PAT:
import msal
import requests
config = {
"authority": "https://login.microsoftonline.com/tenant-id",
"client_id": "client-app-id",
"scope": [ "client-app-id/.default"], # also tried with "499b84ac-1321-427f-aa17-267ca6975798/.default"
"secret": "client-secret",
"endpoint": "https://vssps.dev.azure.com/my-org/_apis/tokens/pats?api-version=7.1-preview.1"
}
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"])
result = app.acquire_token_for_client(scopes=config["scope"])
print(result['access_token'])
pats=requests.post(config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']},
data={"displayName":"new_token1","scope":"vso.packaging_write",
"validTo":"2022-12-01T23:46:23.319Z","allOrgs":"false"})
print(pats.json())
- I have also tried this bash script:
az login --service-principal -u client-id \
-p client-secret --tenant tenant-id
token=`az account get-access-token | jq -r '.accessToken'`
curl -X POST -H "Authorization: Bearer $token " -H "Content-Type:application/json" -H "Accept:application/json" \
-d '{"displayName":"new_token1","scope":"vso.packaging_write","validTo":"2022-12-01T23:46:23.319Z","allOrgs":"false"}' \
'https://vssps.dev.azure.com/my-org/_apis/tokens/pats?api-version=7.1-preview.1'
This doesnt work, get a webpage in response. Please help. Might I be missing permissions or something on the service principal?
We provide a server that spawns user-pods at runtime from our docker images. And within the pods we serve a UI that gives access to the bash terminal. Since our users could be non-technical, we'd like them to have pip.conf/.npmrc files with PATs embedded into the docker image. Is there a way to create PATs in build pipelines, which are not dependent on any actual user (users can get deleted etc) and then embed them into the docker image?
I checked your description and code.
Yes, your permission settings are correct. But from your code it looks like you are trying to use 'client credentials flow' to authenticate, which is definitely not possible at all.
The Azure DevOps API doesn't support non-interactive service access via service principals.
Take a look at this (documentation makes it very clear):
https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/authentication-guidance?view=azure-devops
This document lists all the methods available in the package you use:
https://learn.microsoft.com/en-us/python/api/msal/msal.application.clientapplication?view=azure-python
I think it should be this method (anyway, you need to use 'authorization code flow'):
https://learn.microsoft.com/en-us/python/api/msal/msal.application.clientapplication?view=azure-python#msal-application-clientapplication-acquire-token-by-authorization-code
The way to judge whether it is successful or not is very simple, because you use AAD app to create PAT, so the key is to see if the code running will jump out of the login popup or something (must be interactive, non-interactive is not supported.).