Simplify OAuth refreshToken middleware by using OAuth service in the middleware#13805
Simplify OAuth refreshToken middleware by using OAuth service in the middleware#13805rickyrombo merged 22 commits intomjp-oauth-net-newfrom
Conversation
|
There was a problem hiding this comment.
Pull request overview
This PR refactors the SDK’s OAuth/token-refresh flow to reduce dependencies on generated API clients and to allow OAuth to be instantiated earlier so it can be injected into middleware.
Changes:
- Remove
UsersApidependency fromOAuth(dropisWriteAccessGranted/verifyToken) and perform token verification via direct HTTP request. - Simplify
addTokenRefreshMiddlewareto delegate refresh behavior toOAuth.refreshAccessToken()and retry with the refreshed access token. - Initialize
OAuthearlier increateSdkWithoutServicesand update middleware unit tests to mockOAuthrather thanfetch.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/sdk/src/sdk/oauth/OAuth.ts | Removes UsersApi coupling; implements manual token verification and changes refresh API to return the new access token. |
| packages/sdk/src/sdk/middleware/addTokenRefreshMiddleware.ts | Switches refresh logic from inline fetch/validation to calling oauth.refreshAccessToken(). |
| packages/sdk/src/sdk/middleware/addTokenRefreshMiddleware.test.ts | Updates tests to mock OAuth.refreshAccessToken() instead of mocking cross-fetch. |
| packages/sdk/src/sdk/createSdkWithoutServices.ts | Instantiates OAuth earlier and injects it into the token refresh middleware. |
| packages/sdk/src/sdk/createSdkWithServices.ts | Removes usersApi being passed into OAuth (but currently doesn’t supply basePath). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixes UI for tracks/collections that dont have artwork
Currently when a user comes back from guest account sign up, they enter a sign up purgatory loop where they can't finish their account
- `publishTracks` returns string track IDs, which were being incorrectly parsed as though they were numbers that needed converting. This was changed behavior from recent SDK changes made to match the POST endpoints as this was working previously - `createPlaylist` wasn't equipped to handle using a preset `playlistId` like our client expects, rejecting calls that had `playlistId` already set in the metadata (which would happen on our creation of playlists from scratch). - `createPlaylistInternal` was being passed parsed parameters in the `createPlaylist` case, and unparsed in the `uploadPlaylist` case, and used types that made it hard to squeeze both callsites in. This was resulting in incorrectly setting some IDs to hash IDs (eg in `playlistContents`) and was uncovered when fixing the playlistId bug above - `updatePlaylist` had incorrect schema still referencing `coverArtCid` instead of `playlistImageSizesMultihash`, blocking any playlist updates that included an image update --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1. Top nav CTA If the user is unauthenticated, the button should say “Sign Up.” If the user is authenticated, the button should say “Launch.” 2. Hero CTA The main hero CTA should link to /trending (not Sign Up). 3. Bottom CTA Change the copy from “Get Started” to “Start Exploring.” Link this button to /explore.
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @audius/sdk@14.0.0 ### Major Changes - d864806: Remove getPlaylistByHandleAndSlug in favor of getBulkPlaylists - Removes `sdk.playlists.getPlaylistByHandleAndSlug()` in favor of calling `sdk.playlists.getBulkPlaylists({ permalink: ['/handle/playlist/playlist-name-slug'] })` - Changes return values of `CommentsAPI` to match other APIs, removing `success` param. ### Minor Changes - 71bb31b: Add programmable distribution config to stream_conditions ### Patch Changes - 71bb31b: Fix missing bearer token for PUT /users - a7a9e17: Fix create/upload/update playlist in legacy path - `publishTracks` returns string track IDs, which were being incorrectly parsed as though they were numbers that needed converting. This was changed behavior from recent SDK changes made to match the POST endpoints as this was working previously - `createPlaylist` wasn't equipped to handle using a preset `playlistId` like our client expects, rejecting calls that had `playlistId` already set in the metadata (which would happen on our creation of playlists from scratch). - `createPlaylistInternal` was being passed parsed parameters in the `createPlaylist` case, and unparsed in the `uploadPlaylist` case, and used types that made it hard to squeeze both callsites in. This was resulting in incorrectly setting some IDs to hash IDs (eg in `playlistContents`) and was uncovered when fixing the playlistId bug above - `updatePlaylist` had incorrect schema still referencing `coverArtCid` instead of `playlistImageSizesMultihash`, blocking any playlist updates that included an image update - 8f12bb7: Fix cover art CID metadata properties for playlists and tracks. - 6cb4b6f: Fix UploadsApi to make start() a function ## @audius/sdk-legacy@6.0.21 ### Patch Changes - Updated dependencies [71bb31b] - Updated dependencies [71bb31b] - Updated dependencies [a7a9e17] - Updated dependencies [d864806] - Updated dependencies [8f12bb7] - Updated dependencies [6cb4b6f] - @audius/sdk@14.0.0 ## @audius/sp-actions@1.0.25 ### Patch Changes - @audius/sdk-legacy@6.0.21 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
… entity manager (at least for now) and add support to services-based init + oauth
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@rickyrombo I've opened a new pull request, #13857, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@rickyrombo I've opened a new pull request, #13858, to work on those changes. Once the pull request is ready, I'll request review from you. |
The refresh-token exchange logic was moved into `OAuth.refreshAccessToken()` without corresponding unit tests. This adds focused coverage for that method. ## Tests added (`OAuth.test.ts`) - **Success path** — token store is updated with new access + refresh tokens; new access token is returned - **Request shape** — verifies `grant_type`, `refresh_token`, and `client_id` are sent correctly - **Failure paths**: - Non-OK HTTP response → `null`, token store unchanged - Invalid JSON body → `null` - Missing `access_token` or `refresh_token` in response → `null` - Missing `tokenStore` or `basePath` config → `null` - No refresh token in store → `null` - `fetch` throws (network error) → `null` `jsdom` is not installed in this package, so the browser-only constructor guard is satisfied by stubbing `window` via `vi.stubGlobal`. <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rickyrombo <3690498+rickyrombo@users.noreply.github.com>
`addTokenRefreshMiddleware` was calling `oauth.refreshAccessToken()` on
every 401, including unauthenticated requests, causing
`_surfaceError('No refresh token available.')` to fire as noise on
normal 401 responses.
## Changes
- **`OAuth.hasRefreshToken` getter** — cheap boolean check on
`tokenStore?.refreshToken`
- **Middleware guard** — short-circuits on 401 before attempting refresh
when `hasRefreshToken` is false, avoiding the noisy error callback
entirely
- **Test coverage** — asserts `refreshAccessToken` is never called when
`hasRefreshToken` is false
```ts
// Before: refreshAccessToken() called on every 401 → _surfaceError fired for unauthenticated clients
// After: guard skips refresh entirely when no token is stored
if (!oauth.hasRefreshToken) {
return context.response
}
```
<!-- START COPILOT CODING AGENT TIPS -->
---
🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rickyrombo <3690498+rickyrombo@users.noreply.github.com>
…middleware (#13805) Removes the deps on usersApi by removing the `isWriteAccessGranted` method (which is redundant to the devApps APIs) and the `verifyToken` method (which is redundant with the usersApi) and calling fetch manually internally. Then, this allows the OAuth service to be initialized before other APIs so that it can be used in the config for middlewares to all other APIs. --------- Co-authored-by: Dylan Jeffers <dylan@audius.co> Co-authored-by: Ray Jacobson <ray@audius.co> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Removes the deps on usersApi by removing the
isWriteAccessGrantedmethod (which is redundant to the devApps APIs) and theverifyTokenmethod (which is redundant with the usersApi) and calling fetch manually internally.Then, this allows the OAuth service to be initialized before other APIs so that it can be used in the config for middlewares to all other APIs.