Issues with OneDrive Direct Link Conversion

陳 藝禾 0 Reputation points
2024-12-13T12:29:06.07+00:00

Hello,

I have been successfully using a method to convert OneDrive direct links into a Base64 encoded URL to share content via API, like this:

Original URL:

https://1drv.ms/t/c/b6a769b937e9eff3/EVtvodt7gEhKleFWNTy55vgBTFOziVeKp3kMvqG1wrrROA

Converted Base64 URL:

https://api.onedrive.com/v1.0/shares/u!aHR0cHM6Ly8xZHJ2Lm1zL3QvYy9iNmE3NjliOTM3ZTllZmYzL0VWdHZvZHQ3Z0VoS2xlRldOVHk1NXZnQlRGT3ppVmVLcDNrTXZxRzF3cnJST0E/root/

This was working fine previously. However, recently when I try to access the converted URL, I get the following error:

Error:

{"error":{"code":"unauthenticated","message":"Exception of type 'Microsoft.Vroom.Exceptions.UnauthenticatedVroomException' was thrown."}}

I'm using the following function to encode the URL into Base64:

function encodeBase64Url(url) {

const base64Encoded = btoa(url);  // Base64 encode the URL

const base64Url = base64Encoded

    .replace(/\+/g, '-')  // Replace '+' with '-'

    .replace(/\//g, '_')  // Replace '/' with '_'

    .replace(/=+$/, '');  // Remove '=' padding

return `u!${base64Url}`;  // Add 'u!' prefix

}

const encodedUrl = encodeBase64Url(url);

// Create the download link

const downloadLink = https://api.onedrive.com/v1.0/shares/${encodedUrl}/root/content;

Is there something wrong with my conversion process, or is there a different issue causing the error? Any help in resolving this would be greatly appreciated!

Microsoft 365 and Office | OneDrive | For business | Windows
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Emi Zhang-MSFT 30,051 Reputation points Microsoft External Staff
    2024-12-16T01:12:13.8766667+00:00

    Hi,

    I suggest you post this thread to OneDrive for Developer forum:

    https://techcommunity.microsoft.com/category/onedriveforbusiness/discussions/onedrivedeveloper

    The reason why we recommend posting appropriately is you will get the most qualified pool of respondents, and other partners who read the forums regularly can either share their knowledge or learn from your interaction with us. Thank you for your understanding.


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Lucian Wischik 10 Reputation points
    2025-05-15T21:27:52.3533333+00:00

    You need to get a "badger token". I haven't found documentation on it anywhere.

    Here's complete working code. It uses "createLink" to create a link, shows how to base64 encode the webUrl (or you can just use shareId that's returned from createLink). And it shows how to get the direct link.

    I learned this from https://github.com/felixrieseberg/onedrive-link/issues/1 and https://github.com/rclone/rclone/issues/7898

        // Get driveId. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/drive_get
        const driveResponse = await fetch(`https://api.onedrive.com/v1.0/drive?access_token=${accessToken}`)
        const driveId = (await driveResponse.json()).id;
    
        // Get Music folder id. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/drive_get_specialfolder
        const musicResponse = await fetch(`https://api.onedrive.com/v1.0/drives/${driveId}/special/music?access_token=${accessToken}`)
        const musicId = (await musicResponse.json()).id;
    
        // Create Music/MyFolder1. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_post_children
        const createBody = { name: "MyFolder1", folder: {}, "@microsoft.graph.conflictBehavior": "replace" };
        const createResponse = await fetch(`https://api.onedrive.com/v1.0/drives/${driveId}/items/${musicId}/children?access_token=${accessToken}`, { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(createBody) });
        const folderId = (await createResponse.json()).id;
    
        // Upload Music/MyFolder1/foo.txt. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_put_content
        const fileResponse = await fetch(`https://api.onedrive.com/v1.0/drives/${driveId}/items/${folderId}:/foo.txt:/content?access_token=${accessToken}`, { method: "PUT", headers: { 'Content-Type': 'textplain' }, body: "hello world\n" });
        const fileId = (await fileResponse.json()).id;
    
        // Share Music/MyFolder1. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createlink
        // The docs for "direct endpoint" above say that we must use a namespace prefix for the createLink action.
        // The docs don't actually tell us what that namespace-prefix is, but I discovered that "action.createLink" works.
        const linkBody = { type: "view", scope: "anonymous" };
        const linkResponse = await fetch(`https://api.onedrive.com/v1.0/drives/${driveId}/items/${folderId}/action.createLink?access_token=${accessToken}`, { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(linkBody) });
        const link = await linkResponse.json();
        const shareId = link.shareId;
        const webUrl = link.link.webUrl;
        assert(link.link.scope === "anonymous");
        assert(link.link.type === "view");
        assert(shareId === 'u!' + btoa(webUrl).replace(/=*$/, '').replace('/', '_').replace('+', '-')); // as per https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get
    
        // We'll want a direct-download link to the shareId. But this needs a "badger token", whatever that is...
        // The appId is hard-coded and universal; I presume it's some Microsoft central service?
        // The badgerResponse I've seen so far all indicate an expiry date for the token that's one week out.
        const badgerBody = { appId: '5cbed6ac-a083-4e14-b191-b4ba07653de2' };
        const badgerResponse = await fetch('https://api-badgerp.svc.ms/v1.0/token', { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(badgerBody) });
        const badgerToken = (await badgerResponse.json()).token;
    
        // Get the shared item. https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get
        const getResponse = await fetch(`https://api.onedrive.com/v1.0/shares/${shareId}/driveItem?$expand=children`, { method: "GET", headers: { "Authorization": `Badger ${badgerToken}`, "Prefer": "autoredeem" } });
        console.log(await getResponse.text());
    
        // There's another way to get the shared item, by turning the webUrl into a redeem code...
        const redirectResponse = await fetch(webUrl, { redirect: "manual" });
        assert(redirectResponse.status === 301);
        const redirectParams = new URLSearchParams(new URL(redirectResponse.headers.get('location') || '').search);
        const redeem = redirectParams.get('redeem') || '';
        const getResponse2 = await fetch(`https://api.onedrive.com/v1.0/shares/u!${redeem}/driveItem?$expand=children`, { method: "GET", headers: { "Authorization": `Badger ${badgerToken}`, "Prefer": "autoredeem" } });
        console.log(await getResponse2.text());
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.