authts / react-oidc-context

Lightweight auth library based on oidc-client-ts for React single page applications (SPA). Support for hooks and higher-order components (HOC).
MIT License
701 stars 65 forks source link

How to mock a user to skip authentication for testing #867

Closed barrymichaeldoyle closed 3 weeks ago

barrymichaeldoyle commented 1 year ago

TLDR: I want to skip the auth redirects and mock that process during Cypress tests.

I've been using Mock Service Worker to mock API calls and run Cypress tests to make sure my FE is working correctly based off the expected BE work.

My problem now is I've implemented an AuthGate in my app that will redirect me to my login service to get authenticated.

In my Cypress testing environment I'd love skip this and just mock the user. The problem is I can't not render my auth provider if we're mocking APIs because it will make my code crash since the hooks assume that the provider is present.

I'm sure this is built in to this library and I just don't know where to look. Otherwise, if that's not the case, it would be great to have a prop to add to the AuthProvider that if set will return a mocked user and assume the user is logged in.

All that said, I'm not sure whether or not I'm following industry standards in this regard.

jamierytlewski commented 1 year ago

I second this. If I'm understanding this correctly. I'm not able to figure out how to basically emulate the isAuthenticated So that I can test past the

 if (!auth.isAuthenticated) {
    return <div>Automatically logging you in...</div>;
  }

section.

HansLauBorch commented 1 year ago

TLDR: I want to skip the auth redirects and mock that process during Cypress tests.

I've been using Mock Service Worker to mock API calls and run Cypress tests to make sure my FE is working correctly based off the expected BE work.

My problem now is I've implemented an AuthGate in my app that will redirect me to my login service to get authenticated.

In my Cypress testing environment I'd love skip this and just mock the user. The problem is I can't not render my auth provider if we're mocking APIs because it will make my code crash since the hooks assume that the provider is present.

I'm sure this is built in to this library and I just don't know where to look. Otherwise, if that's not the case, it would be great to have a prop to add to the AuthProvider that if set will return a mocked user and assume the user is logged in.

All that said, I'm not sure whether or not I'm following industry standards in this regard.

If I've understood your question correctly, you want to mock away the OIDC flow and return a mocked user? How I've done this is to first and foremost mock away the OIDC config that returns the essential endpoints required for the OIDC flow:

cy.intercept("GET", "http://localhost:7400/.well-known/openid-configuration", {
        statusCode: 200,
        fixture: "openid-config.json"
    });
// openid-config.json
{
    "issuer": "http://localhost:7400",
    "authorization_endpoint": "http://localhost:7400/authorize",
    "token_endpoint": "http://localhost:7400/token"
}

Afterwards, the OIDC flow will send a request to the token endpoint, so I mock away that token endpoint by doing the following:

cy.intercept("POST", "http://localhost:7400/token", {
        statusCode: 200,
        fixture: "tonytestersonToken.json",
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        }
    });
// tonytestersonToken.json
{
    "access_token": "access_token",
    "refresh_token": "refresh_token",
    "signature": "signature",
    "scope": "refresh_token custom_permissions openid api",
    "id_token": "<change to your id_token>",
    "instance_url": "http://localhost:7400",
    "id": "<change to your id>",
    "token_type": "Bearer",
    "issued_at": "1687254941736"
}

And lastly, you will have to mock away the authorization request and redirect the user back to your redirect endpoint with the code (and the state, if you require a state verification):

cy.intercept("GET", "http://localhost:7400/authorize?*", (req) => {
        req.redirect("http://localhost:5173/?code=1234&state=" + req.query.state);
    });

By changing the id_token to one of your example users id_token, you will have that user as a mocked user in your application.

Hope this helps.

pamapa commented 3 weeks ago

This issue (question) staled some time ago, closing it for now.