question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add example with authentication

See original GitHub issue

The documentation for environments mentions creating a new environment instance whenever the user logs in or out in order to prevent data for different users being cached together. This seems like a very common usage pattern, but the documentation doesn’t show any examples of how to do it. The todo example in this repository doesn’t handle logging in and logging out, so it doesn’t show how to do it, either.

There is a StackOverflow question that discusses how to do this, but it’s light on details. It also refers to storing the environment in component state, which is not shown in the todo example in this repository.

Could you add an example to this repository that shows how to create a fresh environment instance when a user logs in?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
singingwolfboycommented, Sep 3, 2017

Thank you for providing this information, as well. The docs are sorely lacking on this, and I wasn’t aware of that blog post about authentication. However, this still doesn’t resolve my issue.

You say that I have to create a new environment when a user logs in. That’s fine, that’s what I was expecting from the start of filing this issue. What I need is some example code that does that. I don’t know how to create a new environment.

Could you (or someone else who works on Relay) show me how to create a new environment? That’s really what I’m looking for in an authentication example.

3reactions
mike-marcaccicommented, Nov 15, 2017

Hi @singingwolfboy,

Just stumbled on your issue while looking for something else, but I can help. Here’s my environment config file. You can see that I fetch my session ID on each request (which is just stored in the browser’s localStorage) and adds it the the HTTP Authorization header (which is what my API checks).

import {
	Environment,
	Network,
	RecordSource,
	Store,
} from 'relay-runtime';

import * as session from './session';

const source = new RecordSource();
const store = new Store(source);
const network = Network.create(async (
	operation,
	variables,
	cacheConfig,
	uploadables,
) => {
	const headers = {
		'Content-Type': 'application/json',
	};

	// get our session identifier
	const sessionId = session.get();
	if (sessionId) {
		headers['Authorization'] = `Bearer ${sessionId}`;
	}

	// make the HTTP request
	const response = await fetch('/graphql', {
		method: 'POST',
		headers: headers,
		body: JSON.stringify({
			query: operation.text,
			variables: variables,
		}),
	});

	// we are using an invalid session, get rid of it
	if (response.status === 401) {
		session.clear();
	}

	// there was an error communicating with the API
	if (!response.ok) {
		console.error(`API ERROR: ${await response.text()}`);
		throw new Error(response.statusText);
	}

	// parse the JSON response
	return response.json();
});

const environment = new Environment({
	handlerProvider: null,
	network,
	store,
});

export default environment;

Elsewhere in the app, I use a Relay mutation to authenticate (using my API’s authenticate mutation). I use authority and proof here, which is abstract over a bunch of different authentication strategies (ID/Email + Password, Password Reset Token, Google, Facebook, etc) but you can just replace these with whatever you want to use, like username and password. The mutation, if successful, returns a new Session, so we’ll make sure to grab its ID. We then stuff that ID in localStorage so that the next time we make a GraphQL query, we’re authenticated!

const mutation = graphql`
	mutation AuthenticateFormMutation($authority: Authority!, $proof: String!) {
		authenticate(authority: $authority, proof: $proof) {
			message
			session {
				id
			}
		}
	}
`;

Of course, with this strategy you can’t put the entirety of your API behind authentication, since at least the authenticate mutation needs to be accessible without a session.


Perhaps a simpler strategy would be to send a username/password pair with each request, using something like HTTP Basic. This certainly has its security and visibility downsides, but might be an easier way to get a working prototype.

Hope that helps!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Add Login Using the Authorization Code Flow - Auth0
You can add login to your regular web application using the Authorization Code Flow. To learn how the flow works and why you...
Read more >
How To Add Login Authentication to React Applications
By the end of this tutorial, you'll be able to add authentication to a React application and integrate the login and token storage ......
Read more >
Add Authentication to Any Web Page in 10 Minutes
Simple Node Authentication. Add Auth to your PWA with Okta and Stencil. js. Build a React Native Application and Authenticate with OAuth 2.0....
Read more >
Add basic authentication - Nintex Help
You are here: Browse all examples > Add basic authentication ... Basic authentication requires Nintex Workflow Cloud to provide a username and password...
Read more >
Authentication — Requests 2.28.1 documentation
See the requests-oauthlib OAuth2 documentation for details of the various OAuth 2 credential management flows: Web Application Flow. Mobile Application Flow.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found