Azure Artifacts: Maven "401 Unauthorized" from a feed
Maven sends a user name and password to a repository only when settings.xml has a <server> whose <id> is the same as that repository's <id> in pom.xml. Without one, it asks the feed with no credentials, and Azure Artifacts answers 401. So the 401 means either that no server matched, or that the password in it is not accepted (a Stack Overflow question on it from a pipeline has been seen nearly 10,000 times).
When the Maven build fails in a pull request's build validation, the pull request waits on it: Azure DevOps Pull Requests, a plugin for JetBrains IDEs, lists the pull request's branch policies with their state in IntelliJ IDEA, and with Pro runs a failed build policy again once the feed lets the build in. Get it on JetBrains Marketplace
What it looks like
- Maven 3.9:
Could not transfer artifact com.fabrikam:fabrikam-tools:pom:1.0.0 from/to shared (https://pkgs.dev.azure.com/fabrikam/_packaging/shared/maven/v1): status code: 401, reason phrase: Unauthorized (401). - Older Maven:
Authentication failed for https://pkgs.dev.azure.com/fabrikam/_packaging/shared/maven/v1/…/fabrikam-tools-1.0.0.pom 401 Unauthorized, often afterFailed to read artifact descriptor forthe dependency. - On
mvn deploy, the same ending comes afterFailed to deploy artifacts. Dependencies from Maven Central may still download: only the feed is refused.
The server id and the repository id
- Connect to feed, Maven, in Azure Artifacts gives one snippet for
pom.xmland one forsettings.xml. The<id>of the<repository>, in<repositories>and in<distributionManagement>, has to be the same as the<id>of the<server>, letter for letter. If you rename one, rename the other. - If
settings.xmlhas a<mirror>that sends repositories to the feed, Maven uses the mirror's<id>to find the server. The credentials go under that id. - The password is a personal access token with the Packaging scope: Read to restore, Read & write to deploy. The user name can be any text that is not blank (Microsoft's project setup page says so); Microsoft's examples use the organization name or
AzureDevOps. When the token expires, the 401 comes back. - A project-scoped feed has the project in its address,
…/fabrikam/Web/_packaging/shared/maven/v1; an organization-scoped one must not have it. - Keep
settings.xmlwith the token in your user folder (~/.m2/settings.xml), not in the repository.
In a pipeline: MavenAuthenticate before Maven
- Add
- task: MavenAuthenticate@0withartifactsFeeds: sharedbefore the Maven step. It adds a<server>named after each feed to the agent user's~/.m2/settings.xml, so the repository<id>inpom.xmlhas to be the feed's name (the task's reference). Feeds in other organizations go inmavenServiceConnections. - With
mvn -sand your ownsettings.xml, for example from a secure file, the task does not reach that file. Put the server in it yourself, with<username>AzureDevOps</username>and<password>${env.SYSTEM_ACCESSTOKEN}</password>, and give the token to the Maven step:env: SYSTEM_ACCESSTOKEN: $(System.AccessToken). Without that line the step has no such variable, and the feed answers 401. - With MavenAuthenticate in place, leave
mavenAuthenticateFeedon the Maven task at its default, false. In one question, a deploy that failed with 401 worked once the asker set it back to false.
Credentials in place, still 401 or 403
- The build identity has no role on the feed. Restoring needs Feed Reader; deploying needs Feed Publisher (Contributor); saving a package from an upstream source such as Maven Central needs at least Feed and Upstream Reader (Collaborator). The roles, the two build identities and the scope setting are the same as for NuGet: Unable to load the service index for source.
- The feed is in another project. That project has to give the pipeline's build service access, as the MavenAuthenticate reference says.
Gradle
- Gradle does not read
settings.xmlby itself, so MavenAuthenticate does not help it. Withcredentials(PasswordCredentials), which Microsoft's setup for Gradle 8.2 or later uses, it reads two properties named after the repository'snameinbuild.gradle:sharedUsernameandsharedPassword, usually in~/.gradle/gradle.properties(Microsoft's Gradle setup). Its setup for older Gradle uses a plugin that readssettings.xmlinstead. - In a pipeline, give them as environment variables on the Gradle step:
ORG_GRADLE_PROJECT_sharedUsername: AzureDevOpsandORG_GRADLE_PROJECT_sharedPassword: $(System.AccessToken). Gradle turnsORG_GRADLE_PROJECT_variables into project properties (Gradle's build environment page). The build identity needs the same feed roles as for Maven.
Azure DevOps pull requests in IntelliJ IDEA and Rider
Azure DevOps Pull Requests, a plugin by Lesstep for JetBrains IDEs 2024.1 or later and Android Studio, reads the organization, project and repository from your git remote and lists the pull requests that wait for your review in an IDE tool window, on Azure DevOps Services and on Azure DevOps Server. It shows the branch policies of a pull request with their state, so a required build that has not passed is next to its pull request, and with Pro you run a failed or expired build policy again from there. The review inbox is free; voting, commenting, completing and creating are Pro, with a 30-day trial.
Get it on JetBrains Marketplace
Azure DevOps, Azure Artifacts and Azure Pipelines are trademarks of Microsoft Corporation; Apache Maven and Maven are trademarks of the Apache Software Foundation; Gradle is a trademark of Gradle, Inc.; IntelliJ IDEA and Rider are trademarks of JetBrains s.r.o. This page is not affiliated with or endorsed by Microsoft, the Apache Software Foundation, Gradle, Inc. or JetBrains.
More: pip: 401 Error, Credentials not correct for · npm: E401 Unable to authenticate · NuGet: Unable to load the service index for source · 日本語