diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go
index d17e4875b1..c3da5a7513 100644
--- a/routers/api/packages/api.go
+++ b/routers/api/packages/api.go
@@ -610,40 +610,46 @@ func CommonRoutes() *web.Router {
 			}, reqPackageAccess(perm.AccessModeWrite))
 		}, reqPackageAccess(perm.AccessModeRead))
 		r.Group("/swift", func() {
-			r.Group("/{scope}/{name}", func() {
-				r.Group("", func() {
-					r.Get("", swift.EnumeratePackageVersions)
-					r.Get(".json", swift.EnumeratePackageVersions)
-				}, swift.CheckAcceptMediaType(swift.AcceptJSON))
-				r.Group("/{version}", func() {
-					r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
-					r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), swift.UploadPackageFile)
-					r.Get("", func(ctx *context.Context) {
-						// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
+			r.Group("", func() { // Needs to be unauthenticated.
+				r.Post("", swift.CheckAuthenticate)
+				r.Post("/login", swift.CheckAuthenticate)
+			})
+			r.Group("", func() {
+				r.Group("/{scope}/{name}", func() {
+					r.Group("", func() {
+						r.Get("", swift.EnumeratePackageVersions)
+						r.Get(".json", swift.EnumeratePackageVersions)
+					}, swift.CheckAcceptMediaType(swift.AcceptJSON))
+					r.Group("/{version}", func() {
+						r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
+						r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), swift.UploadPackageFile)
+						r.Get("", func(ctx *context.Context) {
+							// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
 
-						version := ctx.PathParam("version")
-						if strings.HasSuffix(version, ".zip") {
-							swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
-							if ctx.Written() {
-								return
+							version := ctx.PathParam("version")
+							if strings.HasSuffix(version, ".zip") {
+								swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
+								if ctx.Written() {
+									return
+								}
+								ctx.SetPathParam("version", version[:len(version)-4])
+								swift.DownloadPackageFile(ctx)
+							} else {
+								swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
+								if ctx.Written() {
+									return
+								}
+								if strings.HasSuffix(version, ".json") {
+									ctx.SetPathParam("version", version[:len(version)-5])
+								}
+								swift.PackageVersionMetadata(ctx)
 							}
-							ctx.SetPathParam("version", version[:len(version)-4])
-							swift.DownloadPackageFile(ctx)
-						} else {
-							swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
-							if ctx.Written() {
-								return
-							}
-							if strings.HasSuffix(version, ".json") {
-								ctx.SetPathParam("version", version[:len(version)-5])
-							}
-							swift.PackageVersionMetadata(ctx)
-						}
+						})
 					})
 				})
-			})
-			r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
-		}, reqPackageAccess(perm.AccessModeRead))
+				r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
+			}, reqPackageAccess(perm.AccessModeRead))
+		})
 		r.Group("/vagrant", func() {
 			r.Group("/authenticate", func() {
 				r.Get("", vagrant.CheckAuthenticate)
diff --git a/routers/api/packages/swift/swift.go b/routers/api/packages/swift/swift.go
index d5d4d4e9d1..4d7fb8b1a6 100644
--- a/routers/api/packages/swift/swift.go
+++ b/routers/api/packages/swift/swift.go
@@ -27,7 +27,7 @@ import (
 	"github.com/hashicorp/go-version"
 )
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
 const (
 	AcceptJSON  = "application/vnd.swift.registry.v1+json"
 	AcceptSwift = "application/vnd.swift.registry.v1+swift"
@@ -35,9 +35,9 @@ const (
 )
 
 var (
-	// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#361-package-scope
+	// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#361-package-scope
 	scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
-	// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#362-package-name
+	// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#362-package-name
 	namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
 )
 
@@ -49,7 +49,7 @@ type headers struct {
 	Link        string
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
 func setResponseHeaders(resp http.ResponseWriter, h *headers) {
 	if h.ContentType != "" {
 		resp.Header().Set("Content-Type", h.ContentType)
@@ -69,7 +69,7 @@ func setResponseHeaders(resp http.ResponseWriter, h *headers) {
 	}
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#33-error-handling
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#33-error-handling
 func apiError(ctx *context.Context, status int, obj any) {
 	// https://www.rfc-editor.org/rfc/rfc7807
 	type Problem struct {
@@ -91,7 +91,7 @@ func apiError(ctx *context.Context, status int, obj any) {
 	})
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
 func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
 	return func(ctx *context.Context) {
 		accept := ctx.Req.Header.Get("Accept")
@@ -101,6 +101,16 @@ func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context
 	}
 }
 
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/PackageRegistryUsage.md#registry-authentication
+func CheckAuthenticate(ctx *context.Context) {
+	if ctx.Doer == nil {
+		apiError(ctx, http.StatusUnauthorized, nil)
+		return
+	}
+
+	ctx.Status(http.StatusOK)
+}
+
 func buildPackageID(scope, name string) string {
 	return scope + "." + name
 }
@@ -113,7 +123,7 @@ type EnumeratePackageVersionsResponse struct {
 	Releases map[string]Release `json:"releases"`
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#41-list-package-releases
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#41-list-package-releases
 func EnumeratePackageVersions(ctx *context.Context) {
 	packageScope := ctx.PathParam("scope")
 	packageName := ctx.PathParam("name")
@@ -170,7 +180,7 @@ type PackageVersionMetadataResponse struct {
 	Metadata  *swift_module.SoftwareSourceCode `json:"metadata"`
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-2
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-2
 func PackageVersionMetadata(ctx *context.Context) {
 	id := buildPackageID(ctx.PathParam("scope"), ctx.PathParam("name"))
 
@@ -228,7 +238,7 @@ func PackageVersionMetadata(ctx *context.Context) {
 	})
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#43-fetch-manifest-for-a-package-release
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#43-fetch-manifest-for-a-package-release
 func DownloadManifest(ctx *context.Context) {
 	packageScope := ctx.PathParam("scope")
 	packageName := ctx.PathParam("name")
@@ -280,7 +290,7 @@ func DownloadManifest(ctx *context.Context) {
 	})
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-6
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-6
 func UploadPackageFile(ctx *context.Context) {
 	packageScope := ctx.PathParam("scope")
 	packageName := ctx.PathParam("name")
@@ -379,7 +389,7 @@ func UploadPackageFile(ctx *context.Context) {
 	ctx.Status(http.StatusCreated)
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-4
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-4
 func DownloadPackageFile(ctx *context.Context) {
 	pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.PathParam("scope"), ctx.PathParam("name")), ctx.PathParam("version"))
 	if err != nil {
@@ -420,7 +430,7 @@ type LookupPackageIdentifiersResponse struct {
 	Identifiers []string `json:"identifiers"`
 }
 
-// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-5
+// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-5
 func LookupPackageIdentifiers(ctx *context.Context) {
 	url := ctx.FormTrim("url")
 	if url == "" {
diff --git a/tests/integration/api_packages_swift_test.go b/tests/integration/api_packages_swift_test.go
index 7d4ff954e2..c0e0dccfab 100644
--- a/tests/integration/api_packages_swift_test.go
+++ b/tests/integration/api_packages_swift_test.go
@@ -42,6 +42,24 @@ func TestPackageSwift(t *testing.T) {
 
 	url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
 
+	t.Run("CheckLogin", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		req := NewRequestWithBody(t, "POST", url, strings.NewReader(""))
+		MakeRequest(t, req, http.StatusUnauthorized)
+
+		req = NewRequestWithBody(t, "POST", url, strings.NewReader("")).
+			AddBasicAuth(user.Name)
+		MakeRequest(t, req, http.StatusOK)
+
+		req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader(""))
+		MakeRequest(t, req, http.StatusUnauthorized)
+
+		req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader("")).
+			AddBasicAuth(user.Name)
+		MakeRequest(t, req, http.StatusOK)
+	})
+
 	t.Run("CheckAcceptMediaType", func(t *testing.T) {
 		defer tests.PrintCurrentTest(t)()