parent
ac1766a62a
commit
b605fdc30a
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@ |
||||
{"key":"accounts/cookies/6ee53737-216c-4984-b530-95b3ff8784ea","payload":{"expires":"2024-11-01T02:16:14.618Z","payload":"93dbc3a7-58f0-424f-be3d-96a7f9eedf33"}} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/data/93dbc3a7-58f0-424f-be3d-96a7f9eedf33","payload":{"linkedLoginsCount":1,"id":"93dbc3a7-58f0-424f-be3d-96a7f9eedf33","**password**":{"decb4d7a-0853-47b0-aeae-d1f98506052f":{"accountId":"93dbc3a7-58f0-424f-be3d-96a7f9eedf33","email":"hello@example.com","password":"$2a$10$UTqS/jXMtrsa9FzMKEw1XeLUi29wqKs16qf8Opx0rF.KACOu6CE2K","verified":true,"id":"decb4d7a-0853-47b0-aeae-d1f98506052f"}},"**clientCredentials**":{},"**pod**":{"b9f98f5e-653d-480c-9e04-78a567580c24":{"baseUrl":"http://localhost:3001/example/","accountId":"93dbc3a7-58f0-424f-be3d-96a7f9eedf33","id":"b9f98f5e-653d-480c-9e04-78a567580c24","**owner**":{"e7464d2a-9987-4564-b7e2-670a3c5c1af4":{"podId":"b9f98f5e-653d-480c-9e04-78a567580c24","webId":"http://localhost:3001/example/profile/card#me","visible":false,"id":"e7464d2a-9987-4564-b7e2-670a3c5c1af4"}}}},"**webIdLink**":{"28985848-10cd-429f-85fa-d1cc78484c52":{"webId":"http://localhost:3001/example/profile/card#me","accountId":"93dbc3a7-58f0-424f-be3d-96a7f9eedf33","id":"28985848-10cd-429f-85fa-d1cc78484c52"}},"rememberLogin":false}} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/owner/e7464d2a-9987-4564-b7e2-670a3c5c1af4","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/password/decb4d7a-0853-47b0-aeae-d1f98506052f","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/password/email/hello%40example.com","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/pod/b9f98f5e-653d-480c-9e04-78a567580c24","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/pod/baseUrl/http%3A%2F%2Flocalhost%3A3001%2Fexample%2F","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/webIdLink/28985848-10cd-429f-85fa-d1cc78484c52","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"accounts/index/webIdLink/webId/http%3A%2F%2Flocalhost%3A3001%2Fexample%2Fprofile%2Fcard%23me","payload":["93dbc3a7-58f0-424f-be3d-96a7f9eedf33"]} |
@ -0,0 +1 @@ |
||||
{"key":"idp/keys/cookie-secret","payload":["aa579c6db82269c7b53b347a94c95ddef902adca35b9094f837748b196b00c94d12c062612cb116a81345c77a7275c02ab112d6c4eb82288d5857570498e67fa"]} |
@ -0,0 +1 @@ |
||||
{"key":"idp/keys/jwks","payload":{"keys":[{"kty":"EC","x":"ZFsT8AmP1xjP28ty6KZx_gWfA9sPycaO9magjOcOVVg","y":"P3hMr5z0q6c4opLXkmKAMyvWRxHIlBLMQ3OFDrl1B1c","crv":"P-256","d":"wF0eIwetdxmZ8fTj5vLAjda13eKzFuOlz72aldsmV7Y","alg":"ES256"}]}} |
@ -0,0 +1 @@ |
||||
{"key":"setup/current-base-url","payload":"http://localhost:3001/"} |
@ -0,0 +1 @@ |
||||
{"key":"setup/current-server-version","payload":"7.1.3"} |
@ -0,0 +1 @@ |
||||
{"key":"setup/v6-migration","payload":true} |
@ -0,0 +1,26 @@ |
||||
# Root ACL resource for the agent account |
||||
@prefix acl: <http://www.w3.org/ns/auth/acl#>. |
||||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. |
||||
|
||||
# The homepage is readable by the public |
||||
<#public> |
||||
a acl:Authorization; |
||||
acl:agentClass foaf:Agent; |
||||
acl:accessTo <./>; |
||||
acl:mode acl:Read. |
||||
|
||||
# The owner has full access to every resource in their pod. |
||||
# Other agents have no access rights, |
||||
# unless specifically authorized in other .acl resources. |
||||
<#owner> |
||||
a acl:Authorization; |
||||
acl:agent <http://localhost:3001/example/profile/card#me>; |
||||
# Optional owner email, to be used for account recovery: |
||||
|
||||
# Set the access to the root storage folder itself |
||||
acl:accessTo <./>; |
||||
# All resources will inherit this authorization, by default |
||||
acl:default <./>; |
||||
# The owner has all of the access modes allowed |
||||
acl:mode |
||||
acl:Read, acl:Write, acl:Control. |
@ -0,0 +1 @@ |
||||
<http://localhost:3001/example/> a <http://www.w3.org/ns/pim/space#Storage>. |
@ -0,0 +1,27 @@ |
||||
# Welcome to your pod |
||||
|
||||
## A place to store your data |
||||
Your pod is a **secure storage space** for your documents and data. |
||||
<br> |
||||
You can choose to share those with other people and apps. |
||||
|
||||
As the owner of this pod, |
||||
identified by <a href="http://localhost:3001/example/profile/card#me">http://localhost:3001/example/profile/card#me</a>, |
||||
you have access to all of your documents. |
||||
|
||||
## Working with your pod |
||||
The easiest way to interact with pods |
||||
is through Solid apps. |
||||
<br> |
||||
For example, |
||||
you can open your pod in [Databrowser](https://solidos.github.io/mashlib/dist/browse.html?uri=http://localhost:3001/example/). |
||||
|
||||
## Accessing your account |
||||
To keep track of your pods, webIDs and any other resources, |
||||
you can [log in](http://localhost:3001/.account/) to your account. |
||||
There you can, for example, update the owners of this pod. |
||||
|
||||
## Learn more |
||||
The [Solid website](https://solidproject.org/) |
||||
and the people on its [forum](https://forum.solidproject.org/) |
||||
will be glad to help you on your journey. |
@ -0,0 +1,14 @@ |
||||
@prefix acl: <http://www.w3.org/ns/auth/acl#>. |
||||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. |
||||
|
||||
<#public> |
||||
a acl:Authorization; |
||||
acl:accessTo <./README>; |
||||
acl:agentClass foaf:Agent; |
||||
acl:mode acl:Read. |
||||
|
||||
<#owner> |
||||
a acl:Authorization; |
||||
acl:accessTo <./README>; |
||||
acl:agent <http://localhost:3001/example/profile/card#me>; |
||||
acl:mode acl:Read, acl:Write, acl:Control. |
@ -0,0 +1,12 @@ |
||||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. |
||||
@prefix solid: <http://www.w3.org/ns/solid/terms#>. |
||||
|
||||
<> |
||||
a foaf:PersonalProfileDocument; |
||||
foaf:maker <http://localhost:3001/example/profile/card#me>; |
||||
foaf:primaryTopic <http://localhost:3001/example/profile/card#me>. |
||||
|
||||
<http://localhost:3001/example/profile/card#me> |
||||
|
||||
solid:oidcIssuer <http://localhost:3001/>; |
||||
a foaf:Person. |
@ -0,0 +1,19 @@ |
||||
# ACL resource for the WebID profile document |
||||
@prefix acl: <http://www.w3.org/ns/auth/acl#>. |
||||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. |
||||
|
||||
# The WebID profile is readable by the public. |
||||
# This is required for discovery and verification, |
||||
# e.g. when checking identity providers. |
||||
<#public> |
||||
a acl:Authorization; |
||||
acl:agentClass foaf:Agent; |
||||
acl:accessTo <./card>; |
||||
acl:mode acl:Read. |
||||
|
||||
# The owner has full access to the profile |
||||
<#owner> |
||||
a acl:Authorization; |
||||
acl:agent <http://localhost:3001/example/profile/card#me>; |
||||
acl:accessTo <./card>; |
||||
acl:mode acl:Read, acl:Write, acl:Control. |
@ -0,0 +1,134 @@ |
||||
import type { KeyPair } from "@inrupt/solid-client-authn-core"; |
||||
import { |
||||
buildAuthenticatedFetch, |
||||
createDpopHeader, |
||||
generateDpopKeyPair, |
||||
} from "@inrupt/solid-client-authn-core"; |
||||
import fetch from "cross-fetch"; |
||||
|
||||
const config = { |
||||
podName: process.env.USER_NAME || "example", |
||||
email: process.env.EMAIL || "hello@example.com", |
||||
password: process.env.PASSWORD || "abc123", |
||||
}; |
||||
|
||||
async function getAuthorization(): Promise<string> { |
||||
// First we request the account API controls to find out where we can log in
|
||||
const indexResponse = await fetch("http://localhost:3001/.account/"); |
||||
const { controls } = await indexResponse.json(); |
||||
|
||||
console.log("First controls", controls); |
||||
|
||||
// And then we log in to the account API
|
||||
const response = await fetch(controls.password.login, { |
||||
method: "POST", |
||||
headers: { "content-type": "application/json" }, |
||||
body: JSON.stringify({ |
||||
email: config.email, |
||||
password: config.password, |
||||
}), |
||||
}); |
||||
// This authorization value will be used to authenticate in the next step
|
||||
const result = await response.json(); |
||||
console.log(result); |
||||
return result.authorization; |
||||
} |
||||
|
||||
async function getSecret( |
||||
authorization: string, |
||||
): Promise<{ id: string; secret: string; resource: string }> { |
||||
// Now that we are logged in, we need to request the updated controls from the server.
|
||||
// These will now have more values than in the previous example.
|
||||
const indexResponse = await fetch("http://localhost:3001/.account/", { |
||||
headers: { authorization: `CSS-Account-Token ${authorization}` }, |
||||
}); |
||||
const { controls } = await indexResponse.json(); |
||||
|
||||
console.log("controls", controls); |
||||
console.log("authorization", authorization); |
||||
|
||||
// Here we request the server to generate a token on our account
|
||||
const response = await fetch(controls.account.clientCredentials, { |
||||
method: "POST", |
||||
headers: { |
||||
authorization: `CSS-Account-Token ${authorization}`, |
||||
"content-type": "application/json", |
||||
}, |
||||
// The name field will be used when generating the ID of your token.
|
||||
// The WebID field determines which WebID you will identify as when using the token.
|
||||
// Only WebIDs linked to your account can be used.
|
||||
body: JSON.stringify({ |
||||
name: "my-token", |
||||
webId: `http://localhost:3001/${config.podName}/profile/card#me`, |
||||
}), |
||||
}); |
||||
|
||||
// These are the identifier and secret of your token.
|
||||
// Store the secret somewhere safe as there is no way to request it again from the server!
|
||||
// The `resource` value can be used to delete the token at a later point in time.
|
||||
const response2 = await response.json(); |
||||
console.log("response2", response2); |
||||
return response2; |
||||
} |
||||
|
||||
async function getAccessToken( |
||||
id: string, |
||||
secret: string, |
||||
): Promise<{ accessToken: string; dpopKey: KeyPair }> { |
||||
try { |
||||
// A key pair is needed for encryption.
|
||||
// This function from `solid-client-authn` generates such a pair for you.
|
||||
console.log("a"); |
||||
const dpopKey = await generateDpopKeyPair(); |
||||
|
||||
// These are the ID and secret generated in the previous step.
|
||||
// Both the ID and the secret need to be form-encoded.
|
||||
const authString = `${encodeURIComponent(id)}:${encodeURIComponent( |
||||
secret, |
||||
)}`;
|
||||
// This URL can be found by looking at the "token_endpoint" field at
|
||||
// http://localhost:3001/.well-known/openid-configuration
|
||||
// if your server is hosted at http://localhost:3000/.
|
||||
const tokenUrl = "http://localhost:3001/.oidc/token"; |
||||
console.log("b"); |
||||
const response = await fetch(tokenUrl, { |
||||
method: "POST", |
||||
headers: { |
||||
// The header needs to be in base64 encoding.
|
||||
authorization: `Basic ${Buffer.from(authString).toString("base64")}`, |
||||
"content-type": "application/x-www-form-urlencoded", |
||||
dpop: await createDpopHeader(tokenUrl, "POST", dpopKey), |
||||
}, |
||||
body: "grant_type=client_credentials&scope=webid", |
||||
}); |
||||
console.log("c"); |
||||
|
||||
// console.log(process.env.JEST_WORKER_ID ?? process.env.NODE_ENV);
|
||||
// console.log(process.env.JEST_WORKER_ID);
|
||||
// console.log(process.env.NODE_ENV);
|
||||
|
||||
console.log("d"); |
||||
|
||||
// This is the Access token that will be used to do an authenticated request to the server.
|
||||
// The JSON also contains an "expires_in" field in seconds,
|
||||
// which you can use to know when you need request a new Access token.
|
||||
const response2 = await response.text(); |
||||
console.log("response2 getAccessToken", response2); |
||||
throw new Error(); |
||||
// return { accessToken: response2.accessToken, dpopKey };
|
||||
} catch (err) { |
||||
console.error(err); |
||||
throw err; |
||||
} |
||||
} |
||||
|
||||
export async function generateAuthFetch() { |
||||
console.log(1); |
||||
const authorization = await getAuthorization(); |
||||
console.log(2); |
||||
const { id, secret } = await getSecret(authorization); |
||||
console.log(3); |
||||
const { accessToken, dpopKey } = await getAccessToken(id, secret); |
||||
console.log(4); |
||||
return await buildAuthenticatedFetch(accessToken, { dpopKey }); |
||||
} |
@ -1,7 +1,9 @@ |
||||
[ |
||||
{ |
||||
"podName": "example", |
||||
"email": "hello@example.com", |
||||
"password": "abc123" |
||||
"password": "abc123", |
||||
"pods": [ |
||||
{ "name": "example" } |
||||
] |
||||
} |
||||
] |
Loading…
Reference in new issue