2 - Authenticating the user
Using the LoginButton
component to log users in
The first thing we need to do in order to be able to write to our Pod is to authenticate as a user with write permissions, so we have the permissions to do so. Luckily, with the login button from solid-ui-react
this is very straightforward.
We need to import LoginButton
from solid-ui-react
. This component accepts two required props: oidcIssuer
, the Pod provider, which in our case will be https://broker.pod.inrupt.com/, and a redirectUrl
which is the URL we want to be redirected to after we login.
The LoginButton
also takes an optional authOptions
prop, which is an object with the clientName
property. This is useful because we want to display our app's name to the user when they authenticate. If we don't pass the clientName
, a random string will be generated which is confusing for the user when they're granting our app permission to do things.
In App.js
let's get rid of all the boilerplate that comes with our React app and use the LoginButton
:
// App.js
import React from "react";
import { LoginButton } from "@inrupt/solid-ui-react";
const authOptions = {
clientName: "Solid Todo App",
};
function App() {
return (
<div className="app-container">
<LoginButton
oidcIssuer="https://broker.pod.inrupt.com/"
redirectUrl={window.location.href}
authOptions={authOptions}
/>
</div>
);
}
export default App;
In the index.js
file, let's wrap our App component with the SessionProvider
component. Now, we can use the useSession
hook throughout the entire app, which returns session info that allows us to make authenticated requests.
Replace the boilerplate in index.js
with the following:
// index.js
import ReactDOM from "react-dom";
import App from "./App";
import { SessionProvider } from "@inrupt/solid-ui-react";
ReactDOM.render(
<SessionProvider>
<App />
</SessionProvider>,
document.getElementById("root")
);
Once that is done, you can test it! Run your app with npm start
and click on the Login button. It should take you to a page where you can either log in or register. If you don't have an account, you can click on "Sign up" to create one. Once you log in, you will be redirected to the main page. As you can see, our main page only has the login button. We are logged in, but we don't do anything with that information. Let's change that!
Using profile data
We're going to change our code so our app shows the login button if we're logged out, and our name if we're logged in.
For this we're going to use CombinedDatasetProvider
and Text
from solid-ui-react
. CombinedDatasetProvider
needs two props: datasetUrl
and thingUrl
, which, in this case, can be both set to the user's WebID.
CombinedDatasetProvider
fetches the dataset and Thing for us so we can pass it straight on to the children.
The child in our app will be the Text
component
The Text
component takes a prop, either property
or properties
, that specifies the value to retrieve and display from the fetched dataset/thing. In our case, we want the Text component to retrieve and display the name of the user from the user's profile. property
or properties
is the URL or URLs we have chosen for the predicate for which we want to fetch the data.
In our case we want to get the name of the user.
<http://example.org/bob#me> <http://xmlns.com/foaf/0.1/knows> <http://example.org/alice#me> .
where <http://example.org/bob#me>
is the subject, <http://xmlns.com/foaf/0.1/knows>
is the predicate and <http://example.org/alice#me>
is the object.To specify that we want to retrieve the name, we use a name identifier. In our example, we use a name identifier from an existing Vocabulary.
The name of the logged in user, in most cases, will be stored in the profile document under "http://www.w3.org/2006/vcard/ns#fn" or "http://xmlns.com/foaf/0.1/name". fn
stands for formatted name. In RDF, that looks like this:
:me <http://www.w3.org/2006/vcard/ns#fn> "Virginia Balseiro" .
or
:me <http://xmlns.com/foaf/0.1/name> "Virginia Balseiro"
But in our case we want it to check under http://www.w3.org/2006/vcard/ns#fn
and if it cannot find anything, check under http://xmlns.com/foaf/0.1/name
. We can use properties
, which is an array of properties to attempt to read from, in our Text
component.
// App.js
import React from "react";
import {
LoginButton,
Text,
useSession,
CombinedDataProvider,
} from "@inrupt/solid-ui-react";
const authOptions = {
clientName: "Solid Todo App",
};
function App() {
const { session } = useSession();
return (
<div className="app-container">
{session.info.isLoggedIn ? (
<CombinedDataProvider
datasetUrl={session.info.webId}
thingUrl={session.info.webId}
>
<div className="message logged-in">
<span>You are logged in as: </span>
<Text properties={[
"http://www.w3.org/2006/vcard/ns#fn",
"http://xmlns.com/foaf/0.1/name",
]} />
</div>
</CombinedDataProvider>
) : (
<div className="message">
<span>You are not logged in. </span>
<LoginButton
oidcIssuer="https://broker.pod.inrupt.com/"
redirectUrl={window.location.href}
authOptions={authOptions}
/>
</div>
)}
</div>
);
}
export default App;
We can now log in and display info from our Pod in our app.
Logging users out
Let's now add a logout button so we can log out whenever we want to. This is easy: we just need to import the LogoutButton
from solid-ui-react
and display it underneath the Text with the user name:
// App.js
import {
LoginButton,
LogoutButton,
Text,
useSession,
CombinedDataProvider,
} from "@inrupt/solid-ui-react";
function App() {
const { session } = useSession();
// ...
<div className="message logged-in">
<span>You are logged in as: </span>
<Text properties={[
"http://xmlns.com/foaf/0.1/name",
"http://www.w3.org/2006/vcard/ns#fn",
]} />
<LogoutButton />
</div>
// ...
}
d206fe2