Basic question about URL to use when making a request

Hi! I’m working on a server app, written in Swift. So, am building up some networking request code of my own. I’m working from solid-spec/api-rest.md at master · solid/solid-spec · GitHub

In related work, I’m already able to get a refresh token, generate access tokens, and sign DPoP’s (see GitHub - crspybits/SolidAuthSwift: Swift-based authentication for a Solid Pod).

I’m trying to figure out what URL to use when making a request. For example, in solid-spec/api-rest.md at master · solid/solid-spec · GitHub they give an example for container creation:

POST / HTTP/1.1
Host: example.org
Content-Type: text/turtle
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
Slug: data

Using URLSession and URLRequest to make the actual networking request in Swift, along with this, I pass additional headers:

authorization: "DPoP <ACCESSTOKEN>",
dpop: "<DPOPTOKEN>"

where <ACCESSTOKEN> is the access token I’ve successfully obtained from the solid server, and <DPOPTOKEN> is the signed DPoP token I’ve generated.

I have an account on inrupt.net (https://crspybits.inrupt.net/profile/card#me), but using that URL in place of the Host above isn’t working.

E.g., I get back:

"<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>Log in</title>\n  <link rel=\"stylesheet\" href=\"/common/css/bootstrap.min.css\">\n  <link rel=\"stylesheet\" href=\"/common/css/solid.css\">\n</head>\n<body>\n<div class=\"container\">\n  <div class=\"page-header\">\n    <div class=\"pull-right\">\n      <button id=\"register\" type=\"button\" class=\"btn btn-primary\">Register</button>\n      <button id=\"login\"    type=\"button\" class=\"btn btn-success\">Log in</button>\n      <button id=\"logout\"   type=\"button\" class=\"hidden btn btn-danger\">Log out</button>\n    </div>\n    <h1>Log in to access this resource</h1>\n  </div>\n\n  <div class=\"alert alert-danger\">\n    <p>\n      The resource you are trying to access\n      (<code>https://crspybits.inrupt.net/profile/card</code>)\n      requires you to log in.\n    </p>\n  </div>\n\n</div>\n</div>\n<script src=\"/common/js/solid-auth-client.bundle.js\"></script>\n<script src=\"/common/js/auth-buttons.js\"></script>\n</body>\n</html>"

which I assume just means I’m using the wrong URL. Any suggestions appreciated.

Happy to share the specific Swift code, but this just seems like a basic question.

It looks like you are trying to POST to you profile. I’d be very careful about that since if you mess up your profile, it will be hard to access your pod. Also in a POST the Host should be the parent Container and the Slug should be the resource. Content you want to send should be in the body. So if I want to POST to http://example.org/foo/bar.ttl my POST would have http://example.org/foo/ as the Host an bar.ttl as the Slug. But also be aware that POST will not behave as you expect - if the resource already exists, POST will create a duplicate with a random number prefixed on the file name. Use PUT to overwrite a resource.

Thanks, @jeffz! So, in my case with my account https://crspybits.inrupt.net what would http://example.org be replaced with from your example?

I just tried that. I used these headers:

"Content-Type": "text/turtle"
"Link": "<http://www.w3.org/ns/ldp#BasicContainer>; rel=\"type\""
"Dpop": "<snip>"
"Authorization": "DPoP <snip>"
"Slug": "NewDirectory"

I sent the request to:

https://crspybits.inrupt.net

I get:
Response: 401 status code, and:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Log in</title>
  <link rel="stylesheet" href="/common/css/bootstrap.min.css">
  <link rel="stylesheet" href="/common/css/solid.css">
</head>
<body>
<div class="container">
  <div class="page-header">
    <div class="pull-right">
      <button id="register" type="button" class="btn btn-primary">Register</button>
      <button id="login"    type="button" class="btn btn-success">Log in</button>
      <button id="logout"   type="button" class="hidden btn btn-danger">Log out</button>
    </div>
    <h1>Log in to access this resource</h1>
  </div>

  <div class="alert alert-danger">
    <p>
      The resource you are trying to access
      (<code>https://crspybits.inrupt.net/</code>)
      requires you to log in.
    </p>
  </div>

</div>
</div>
<script src="/common/js/solid-auth-client.bundle.js"></script>
<script src="/common/js/auth-buttons.js"></script>
</body>
</html>

https://crspybits.inrupt.net” is an IDP address - it has no trailing slash when used to identify an oidc-issuer. But it is not a valid Solid URL which needs to end in a slash if it is a container. So if your new container is named “foo”, your POST should have host=“https://crispybits.inrupt.net/” and slug=“foo”. That should create the container https://crispybits.inrupt.net/foo/".

However, the error you are showing is an unauthorized error. Perhaps that’s an artifact of using the wrong host or else your DPoP stuff is wrong, or else your app is not listed as a trustedApp in your profile.

Hmmm. Just put a trailing slash on https://crispybits.inrupt.net/ and same result. The DPoP stuff being wrong is possible, though I have used it to successfully request the access token (Solid OIDC Primer).

I’m not knowing about the trustedApp part. I think I’ve pretty carefully carried out the steps in Solid OIDC Primer. I certainly haven’t taken any steps on the issuer side (e.g., through a web UI) to make my app a trustedApp. Not sure either how that would work right now since my “app” is just some test code running on my laptop.

Not seeing anything useful looking on a web search for “trustedApp Solid Project”. Could you please pass me some references?

Thanks!

The trustedApp protocol is NOT in the spec and will be replaced but IS currently enforced on NSS servers like inrupt.net for browser-based apps but is not enforced for out-of-browser apps. So, unless you are sending your requests via a localhost or other browser-based context, you shouldn’t need to worry about trustedApps. The only docs on trustedApps I know about are here : GitHub - solid/userguide: userguide to data browser

Just signed into the Solid web UI for my account, and I see the trusted app setup.

From what I can tell, my app is indeed a trusted app. I.e., this is my application URL biz.spasticmuffin.neebla.demo://– good to see this in the web UI :slight_smile:

I believe that got setup during the registration part of my authorization.

My requests are definitely not coming from a browser. They are coming from some Swift code running on Linux in a Docker container.

It seems like I need to overtly use a host header. I’d not been using one. Not sure in my case what it’s value ought to be but I just tried:

host: crspybits.inrupt.net

and

host: inrupt.net

and in both cases, I get the same error as above.

Drum roll please…

It’s working! My first working request:

I had been getting one of the claims in my DPoP incorrect.

Specially, the htu field in the DPoP body was supposed to be the URL I was using in the request, but it actually wasn’t.

I also did use:

host: crspybits.inrupt.net

in this successful request.

:+1: :+1: Congratulations!

I should mention though that this doesn’t really test your login. The inbox, unless you changed its permissions is world-appendable so anyone can POST things there.

Thank you, and thanks for your help!! I’ll try to remember to post a link to the github repo with the working code. Have some cleanup to do.

I’m not really understanding the inbox comment. My new directory doesn’t seem to be under my inbox.

Or am I missing something? I’m still pretty wet behind the ears when it comes to Solid.

Oh, my bad eyes. I thought your new directory was inside the inbox. Nevermind. :slight_smile:

Right. I was a bit confused about the UX of the nesting in the web UI too. Had to stare at it a bit. I’m not sure if my directory placement is conventional. What I intend in the end is to create a top level container/directory named for my app.

“Top level” means different things on different servers. There is no reliable way to find a person’s pod storage space from a webid. You can climb the container tree till you find a container with a link header asserting that the container is a pim:Storage. Polite apps should ask the user where the app-specific data should be stored.

I’m submitting an issue about the indentation of the folders in the databrowser and I’ll use your screenshot as an example. :-). See Make active item flush with siblings in databrowser · Issue #44 · solid/solidos · GitHub

I’m assuming an answer to this question from the user would take the form of a path “foo1/foo2/foo3” etc. that I would then append to their base URL. E.g., in my case “https://crspybits.inrupt.net/foo1/foo2/foo3”. Is that what you mean?

While I’m thinking of it, here’s the code, in Swift for the Solid component of my server:

Incomplete, but much of the basics are in place.