15

I'm trying to fetch a curl and get a JSON from an API.

curl -XPOST -d "grant_type=password" -d "username=admin@admin.admin" \
    -d "password=admin" "web_app@localhost:8081/oauth/token"

When I use the curl in terminal everything works fine but trying it with a fetch I get the error message mentioned at the bottom.

fetch("http://web_app@localhost:8081/oauth/token", {
        credentials: 'include',
        body: "grant_type=password&username=admin@admin.admin&password=admin",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded",
        },
        method: "POST"
    }

This is the error I get:

TypeError: http://web_app@localhost:8081/oauth/token is an url with embedded credentials.

Is the fetch I did wrong?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
CptRivaille
  • 169
  • 1
  • 1
  • 5

2 Answers2

27

You can't use the https://user:pass@host.com form, you need to set the Authorization http Header:

var headers = new Headers({
    'Authorization': `Basic ${btoa(username + ':' + password)}`
});

fetch('https://host.com', {headers: headers})

Where btoa encodes 'user:pass' to base64 encoded string. You can find btoa function availability on MDN (in short: it works on IE 10 and above).

exside
  • 3,736
  • 1
  • 12
  • 19
Will Munn
  • 7,363
  • 4
  • 27
  • 32
  • 10
    What is the reason for this? – felixfbecker Dec 06 '18 at 00:32
  • 1
    @felixfbecker I'm not 100% sure but it could be b/c of security reasons... you aren't allowed to store auth-url into the cache storage api. and if the service worker could read the `request.url` then that would also be reviled in the javascript context, but what is stopping u from reading the headers? I also would like to know the exact reason for this disallowance – Endless Sep 07 '21 at 09:15
  • `btoa()` is deprecated. Use this instead: `Buffer.from(username + ':' + password, "binary").toString("base64");` – Raman Sinclair Feb 05 '23 at 22:03
  • 2
    @Arsinclair that's right in nodejs but not in the browser – Will Munn Feb 07 '23 at 05:50
-2

the fetch request contains embedded credentials, which is not allowed in the web browser's Fetch API. To possibly solve this issue, you can separate the credentials from the URL and pass them using the credentials option.

Here's an updated version of your fetch request:

fetch("http://localhost:8081/oauth/token", {
    credentials: 'include',
    body: "grant_type=password&username=admin@admin.admin&password=admin",
    headers: {
        "Authorization": "Basic " + btoa("web_app:"),
        "Content-Type": "application/x-www-form-urlencoded"
    },
    method: "POST"
})
    .then(response => response.json())
    .then(data => {
        // Handle the JSON response
        console.log(data);
    })
    .catch(error => {
        // Handle any errors
        console.error(error);
    });

In this updated code, the URL is modified to remove the embedded credentials (web_app@) and is replaced with just http://localhost:8081/oauth/token.

To pass the credentials, the Authorization header is set using the btoa function to encode the client ID (web_app) as a Basic Authentication header. Note that the colon (:) is added after the client ID to represent an empty password.

Make sure you replace the http://localhost:8081/oauth/token with the correct URL for your API endpoint. You could also, handle the response and error appropriately in the then and catch blocks also. I hope this can help you ,and this could be what your looking for.

rainmanp7
  • 1
  • 1