Giter Site home page Giter Site logo

auth0 / auth0-spa-js Goto Github PK

View Code? Open in Web Editor NEW
878.0 25.0 346.0 8.19 MB

Auth0 authentication for Single Page Applications (SPA) with PKCE

License: MIT License

TypeScript 59.27% JavaScript 32.20% HTML 8.53%
auth0-js pkce openid-connect oauth2 spa dx-sdk javascript auth0

auth0-spa-js's Introduction

Auth0 SDK for Single Page Applications using Authorization Code Grant Flow with PKCE.

Release Codecov Downloads License CircleCI

📚 Documentation - 🚀 Getting Started - 💻 API Reference - 💬 Feedback

Documentation

  • Quickstart - our interactive guide for quickly adding login, logout and user information to your app using Auth0.
  • Sample app - a full-fledged sample app integrated with Auth0.
  • FAQs - frequently asked questions about auth0-spa-js SDK.
  • Examples - code samples for common scenarios.
  • Docs Site - explore our Docs site and learn more about Auth0.

Getting Started

Installation

Using npm in your project directory run the following command:

npm install @auth0/auth0-spa-js

From the CDN:

<script src="https://cdn.auth0.com/js/auth0-spa-js/2.1/auth0-spa-js.production.js"></script>

Configure Auth0

Create a Single Page Application in the Auth0 Dashboard.

If you're using an existing application, verify that you have configured the following settings in your Single Page Application:

  • Click on the "Settings" tab of your application's page.
  • Scroll down and click on the "Show Advanced Settings" link.
  • Under "Advanced Settings", click on the "OAuth" tab.
  • Ensure that "JsonWebToken Signature Algorithm" is set to RS256 and that "OIDC Conformant" is enabled.

Next, configure the following URLs for your application under the "Application URIs" section of the "Settings" page:

  • Allowed Callback URLs: http://localhost:3000
  • Allowed Logout URLs: http://localhost:3000
  • Allowed Web Origins: http://localhost:3000

These URLs should reflect the origins that your application is running on. Allowed Callback URLs may also include a path, depending on where you're handling the callback (see below).

Take note of the Client ID and Domain values under the "Basic Information" section. You'll need these values in the next step.

Configure the SDK

Create an Auth0Client instance before rendering or initializing your application. You should only have one instance of the client.

import { createAuth0Client } from '@auth0/auth0-spa-js';

//with async/await
const auth0 = await createAuth0Client({
  domain: '<AUTH0_DOMAIN>',
  clientId: '<AUTH0_CLIENT_ID>',
  authorizationParams: {
    redirect_uri: '<MY_CALLBACK_URL>'
  }
});

//or, you can just instantiate the client on its own
import { Auth0Client } from '@auth0/auth0-spa-js';

const auth0 = new Auth0Client({
  domain: '<AUTH0_DOMAIN>',
  clientId: '<AUTH0_CLIENT_ID>',
  authorizationParams: {
    redirect_uri: '<MY_CALLBACK_URL>'
  }
});

//if you do this, you'll need to check the session yourself
try {
  await auth0.getTokenSilently();
} catch (error) {
  if (error.error !== 'login_required') {
    throw error;
  }
}

Logging In

You can then use login using the Auth0Client instance you created:

<button id="login">Click to Login</button>
//redirect to the Universal Login Page
document.getElementById('login').addEventListener('click', async () => {
  await auth0.loginWithRedirect();
});

//in your callback route (<MY_CALLBACK_URL>)
window.addEventListener('load', async () => {
  const redirectResult = await auth0.handleRedirectCallback();
  //logged in. you can get the user profile like this:
  const user = await auth0.getUser();
  console.log(user);
});

For other comprehensive examples, see the EXAMPLES.md document.

API Reference

Explore API Methods available in auth0-spa-js.

Feedback

Contributing

We appreciate feedback and contribution to this repo! Before you get started, please see the following:

Raise an issue

To provide feedback or report a bug, please raise an issue on our issue tracker.

Vulnerability Reporting

Please do not report security vulnerabilities on the public GitHub issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.

What is Auth0?

Auth0 Logo

Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout Why Auth0?

This project is licensed under the MIT license. See the LICENSE file for more info.

auth0-spa-js's People

Contributors

adamjel avatar adamjmcgrath avatar cocojoe avatar crew-security avatar damieng avatar dannnir avatar davidpatrick avatar degrammer avatar dependabot-preview[bot] avatar dependabot[bot] avatar evansims avatar ewanharris avatar frederikprijck avatar gkwang avatar lbalmaceda avatar luisrudge avatar mdlavin avatar nkete avatar picosam avatar reify-tanner-stirrat avatar rnwolfe avatar seyyedkhandon avatar slaywell avatar snyk-bot avatar soviut avatar stevehobbsdev avatar thundermiracle avatar widcket avatar willhackett avatar yinzara avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

auth0-spa-js's Issues

Links broken on https://auth0.github.io/auth0-spa-js/

I noticed that most of the links to local files in this repo are broken on the https://auth0.github.io/auth0-spa-js/ site.

Also, the "Be sure to review the contributing guidelines" message I'm seeing on GH as I type this issue links to a 404 as well (https://github.com/auth0/auth0-spa-js/blob/master/CONTRIBUTING.md). (I swear this was broken a moment ago!)

Cheers

Typescript fails with auth0-spa-js

Hello,

I'm using the same example of the auth0-spa-js quickstart with typescript and it fails all the time.

this is the code:

import * as React from "react";
import createAuth0Client from '@auth0/auth0-spa-js'
// already tried also
// import * as createAuth0Client from '@auth0/auth0-spa-js'

import {canUseDom} from "../domUtils";


type ProviderProps = Auth0ClientOptions & {
  onRedirectCallback: any,
  ssrUser: any
}

type ContextValueType = {
  isAuthenticated?: boolean,
  user?: any,
  loading?: boolean,
  popupOpen?: boolean,
  loginWithPopup?: (params: any) => void,
  handleRedirectCallback?: () => void,
  getIdTokenClaims?: (...p: any) => any,
  loginWithRedirect?: (...p: any) => any,
  getTokenSilently?: (...p: any) => any,
  getTokenWithPopup?: (...p: any) => any,
  logout?: (...p: any) => any
}

const DEFAULT_REDIRECT_CALLBACK = (appState: any) =>
  // @ts-ignore
  canUseDom() ? window.history.replaceState({}, document.title, window.location.pathname) : null;

export const Auth0Context = React.createContext<ContextValueType>({});
export const useAuth0 = () => React.useContext(Auth0Context);


export const Auth0Provider: React.FC<ProviderProps> = ({
                                children,
                                ssrUser,
                                onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
                                ...initOptions
                              }) => {
 
  const [isAuthenticated, setIsAuthenticated] = React.useState();
  const [user, setUser] = React.useState();
  const [auth0Client, setAuth0] = React.useState();
  const [loading, setLoading] = React.useState(true);
  const [popupOpen, setPopupOpen] = React.useState(false);

  if(ssrUser){
    setUser(ssrUser)
    setIsAuthenticated(!!ssrUser)
  }

  React.useEffect(() => {

      const initAuth0 = async () => {
       
       // **it breaks here!**
        const auth0FromHook = await createAuth0Client(initOptions);

        setAuth0(auth0FromHook);

        if (canUseDom() && window.location.search.includes("code=")) {
          const {appState} = await auth0FromHook.handleRedirectCallback();
          onRedirectCallback(appState);
        }

        const isAuthenticated = await auth0FromHook.isAuthenticated();

        setIsAuthenticated(isAuthenticated);

        if (isAuthenticated) {
          const user = await auth0FromHook.getUser();
          setUser(user);
        }

        setLoading(false);
      };
      initAuth0();

    // eslint-disable-next-line
  }, []);

  const loginWithPopup = async (params = {}) => {
    setPopupOpen(true);
    try {
      await auth0Client.loginWithPopup(params);
    } catch (error) {
      console.error(error);
    } finally {
      setPopupOpen(false);
    }
    const user = await auth0Client.getUser();
    setUser(user);
    setIsAuthenticated(true);
  };

  const handleRedirectCallback = async () => {
    setLoading(true);
    await auth0Client.handleRedirectCallback();
    const user = await auth0Client.getUser();
    setLoading(false);
    setIsAuthenticated(true);
    setUser(user);
  };


  return (
    <Auth0Context.Provider
      value={{
        isAuthenticated,
        user,
        loading,
        popupOpen,
        loginWithPopup,
        handleRedirectCallback,
        getIdTokenClaims: (...p: any) => auth0Client.getIdTokenClaims(...p),
        loginWithRedirect: (...p: any) => auth0Client.loginWithRedirect(...p),
        getTokenSilently: (...p: any) => auth0Client.getTokenSilently(...p),
        getTokenWithPopup: (...p: any) => auth0Client.getTokenWithPopup(...p),
        logout: (...p: any) => auth0Client.logout(...p)
      }}
    >
      {children}
    </Auth0Context.Provider>
  );
};


When I'm trying to use this component then I got the error :

Unhandled Rejection (TypeError): auth0_spa_js_1.default is not a function

Captura de pantalla 2019-07-11 a las 11 27 21

I've been dealing with this issue for days and no solution yet. I'm kinda in a hurry right now. Have anyone of you experienced this?

kind regards,
Ibrael

Failed to minify the code from this file - on npm build

Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file:

        ./node_modules/@auth0/auth0-spa-js/dist/auth0-spa-js.production.js:1:12440

I'm getting the above error when attempting to run npm build on my create-react-app created application.

I'm running:
"@auth0/auth0-spa-js": "^1.0.1",
"react-scripts": "^2.1.3",

How to get a management api access token?

I'm trying to get an access token to be able to change some user metadata. This is what I have so far:

async getAuth0Client(): Promise<Auth0Client> {
  if (!this.auth0Client) {
    this.auth0Client = await createAuth0Client(this.config);

    // Provide the current value of isAuthenticated
    this.isAuthenticated.next(await this.auth0Client.isAuthenticated());

    // Whenever isAuthenticated changes, provide the current value of `getUser`
    this.isAuthenticated.subscribe(async isAuthenticated => {
      if (isAuthenticated) {
        this.profile.next(await this.auth0Client.getUser());
        this.backendToken.next(await this.auth0Client.getTokenWithPopup());
        this.managementToken.next(await this.auth0Client.getTokenWithPopup({
          audience: 'https://{project}.{region}.auth0.com/api/v2/',
          scope: 'update:users update:users_app_metadata'
        }));

        return;
      }

      this.profile.next(null);
    });
  }

  return this.auth0Client;
}

However, my managementToken only contains the usual scopes openid email profile, not the ones I explicitly stated.
The profile contains the user metadata I set via the auth0-website, but I cannot update it via this.http.patch(http://{project}.{region}.auth0.com/api/v2/users/${this.profile.sub}, this.profile).
I also tried to create a second auth0Client for the management api, but this mixes up the state when authenticating. Any idea what I'm doing wrong?

Syntax Error on IE

The lib was erroring on our project in IE 11 after updating to the spa lib from lock, and when testing with the demo application we get the same error. It looks like it's using some es6 syntax in the module (spread operator). I'm using differential loading, but it doesn't look like it effects node_modules. below are the errors from the demo app.

This is on IE 11.0.9600

Perhaps i'm doing something wrong in the configuration, but i can't find anything.

Thanks.
Screen Shot 2019-07-19 at 3 47 11 PM
Screen Shot 2019-07-19 at 3 56 08 PM

Deploying to http environment causes error on `loginWithRedirect`

We have an environment deployed on Azure which is used for test automation. Currently, as it is limited by ip address, we don't have https set up on this environment.

When we do a build of our code with this library incorporated, I get and error when I hit the login button, which is in turn calling loginWithRedirect. We use a slightly modified version of the Auth0 React wrapper from the examples, but is verbatim of the example for the loginWithRedirect function.

The error I get (which could be clearer or mitigated against possibly) is:

Uncaught (in promise) TypeError: Cannot read property 'digest' of undefined
    at q (auth0-spa-js.production.js:570)
    at t.<anonymous> (auth0-spa-js.production.js:1052)
    at u (runtime.js:45)
    at Generator._invoke (runtime.js:264)
    at Generator.e.<computed> [as next] (runtime.js:98)
    at auth0-spa-js.production.js:66
    at new Promise (<anonymous>)
    at n (auth0-spa-js.production.js:43)
    at t.value (auth0-spa-js.production.js:1037)
    at loginWithRedirect (Auth.tsx:151)

which points to line 570 of auth0-spa-js.production.js, which on mine reads:

569      N = function N(e) {
570    return window.crypto.subtle.digest({
571      name: "SHA-256"
572    }, new TextEncoder().encode(e));

If this library is not intended to be ran in http in a prod environment, then I think that needs to be made clear. If it should "cope", then some checking and handling needs to be done here too.

auth0 spa not working with angular interceptor

Hi auth0 team.

I tried to use the angular http interceptor to set headers in the request.

But when I added the httpInterceptor service, auth0-spa package not working.

the function isAuthenticated() is not working, seem like the request url to the auth0 is replace (but I did nothing with the url in the interceptor).
Here is the request URL:
https://authorize/?client_id=&audience=&scope=openid%20profile%20email&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fauth0%2Fcallback&response_type=code&response_mode=web_message&state=WXNwOE1jUGVrMDg3NjU2dVBPSzc1aFZIRHJjfjduWnRSbmF5eTk5UjIwZw%3D%3D&nonce=QJ94AvDv.tski5fNTffzNy35Zyx7AZHZkHg93XRb.Al&code_challenge=XW6i-5f14LC0KYpyBVQY28uLJ0JJLJ34RT2Z9iCuvzI&code_challenge_method=S256&prompt=none&auth0Client=eyJuYW1lIjoiYXV0aDAtc3BhLWpzIiwidmVyc2lvbiI6IjEuMC4xIn0%3D

I did notice that the request url is being replace and now it only https://.
If I remove the http interceptor, the request url will be https://my-domain.com/authorize/.... and it work perfectly.

The interceptor service:

export class HttpInterceptorService implements HttpInterceptor {
    token: string;

    constructor(private _router: Router,
                private _dialog: MatDialog,
                private _auth0Service: AuthService,
                private _messageService: MessageService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this._messageService.startFetchingData();
        console.log(request);
        console.log(`start fetching data`);
        this._auth0Service.token.subscribe(_token => this.token = _token );

        request = request.clone({
            setHeaders: {
                Authorization: 'Bearer ' + this.token
            }
        });

        return next.handle(request).pipe(
            tap((event: HttpEvent<any>) => {
                // catch http response
                if (event instanceof HttpResponse) {
                    this._messageService.finishFetchingData();
                }
                console.log(`finish fetching data`);
                return event;
            }),
            catchError((httpErrorResponse: HttpErrorResponse) => {
                this._messageService.finishFetchingData();

                switch (httpErrorResponse.status) {
                    case 500: {
                        this._dialog.open( Error500DialogComponent, {
                            autoFocus: false
                        });
                        break;
                    }

                    case 401: {
                        this._router.navigate(['/public/signin']);
                        break;
                    }
                }

                return throwError(httpErrorResponse);
            })
        );
    }
}

Auth0 Example not working

Hi,

I've just downloaded the example app from the auth0 page and it seems it's not working. After looking at the URL the login process generates I've noticed this:

error_description=Cannot read property 'persons' of undefined

What am I missing?

How would one go about accessing RBAC permissions

Hi,

Would be great to be able to access RBAC (Authorization Core) permissions in the SPA so as to be able to extend the PrivateRoute component to restrict routes based on permission.

Can see how to get the permissions included in the access token for my API but unsure how to get access to them in the SPA.

Many thanks, Ed

`RedirectLoginOptions` has no default

Hi there,

I've experimenting with the new library and it looks like the default value of { } is not set for the RedirectLoginOptions in the loginWithRedirect method.

When I call the method like this:

client.loginWithRedirect();

I get the error:

TypeError: r is undefined

But if I call it with an empty Object, everything works fine:

client.loginWithRedirect({});

I'm not familiar with TypeScript, but when I look at the code, a default value is set:
https://github.com/auth0/auth0-spa-js/blob/master/src/Auth0Client.ts#L194

However, when I check the compiled file auth0-spa-js.production.js:834, it's missing:

loginWithRedirect(r) { // no default value is set
  return t(this, void 0, void 0, function* () {
    const t = r.redirect_uri,
          o = r.appState,
          n = e(r, ["redirect_uri", "appState"]),
          i = A(k()),
          a = k(),
          s = k(),
          c = yield N(s),
          l = F(c),
          d = this._getParams(n, i, a, l, t),
          u = this._authorizeUrl(d);

    this.transactionManager.create(i, {
      nonce: a,
      code_verifier: s,
      appState: o,
      scope: d.scope,
      audience: d.audience || "default"
    }), window.location.assign(u);
  });
}

Any idea why this is happening? I'm happy to send a PR with a fix if needed.

On a side note, the link to the Auth0's contribution guidelines in CONTRIBUTING.md seems to be broken. It links to GENERAL-CONTRIBUTING.md, but it looks like that file is not present in this repo:
https://github.com/auth0/auth0-spa-js/blob/master/GENERAL-CONTRIBUTING.md

Expose auth0Client globally

I've followed the SPA quick start guide and got it working. My problem now is that that guide kinda forces you to manage authentication through your component tree by having the Auth0Context around your entire app. Is there any problem in exposing the auth0Client globally to the app? My issue is regarding API calls. Following the guide, I realized that I need to call getTokenSilently but the way the guide puts it this is only available inside component functions. If I want to have an API module the deals with API calls only how can I access the auth0Client? Am I thinking this wrong?

Thank you!

ERROR TypeError: auth0_spa_js_1.default is not a function

Hi Guys,

Using this new library I am getting this error all the time, not sure why:

core.js:15724 ERROR TypeError: auth0_spa_js_1.default is not a function
    at auth0.service.ts:32
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:498)
    at ZoneTask.invoke (zone.js:487)
    at timer (zone.js:2281)

And here is my code:

private auth0Client: Auth0Client;

  // Auth0 application configuration responseType: 'token id_token',
  config: Auth0ClientOptions = {
    domain: 'my.custom.domain',
    client_id: 'MY_CLIENT_ID',
    redirect_uri: `${ window.location.origin }/callback`,
    scope: 'openid profile email',
    audience: 'https://myapi.auth0.com/api/v2/',
    display: 'popup',
    prompt: 'login'
  };

  constructor() {
    setTimeout( () => {
      from(createAuth0Client(this.config)).subscribe( (client: Auth0Client) => {
        this.auth0Client = client;
        console.log(`createAuth0Client: ${ JSON.stringify(client) }`);
        this.authClientSubject.next(this.auth0Client);
      });
    }, 1000);
  }

I've tried using setTimeout and without, always the same, createAuth0Client is undefined :(

Any idea?

Thanks.

auth0-spa-js.production.legacy.js default export is undefined

hi, Currently I have some problems with the transpilation of auth0-spa-js.production.js

Failed to compile.
Failed to minify the code from this file: 
 	./node_modules/@auth0/auth0-spa-js/dist/auth0-spa-js.production.js:1:12440 
Read more here: http://bit.ly/2tRViJ9
error Command failed with exit code 1.

I tried to use the build auth0-spa-js.production.legacy.js, but it fails

import createAuth0Client from "@auth0/auth0-spa-js"; 

 const auth0FromHook = await createAuth0Client(initOptions);

webpack alias:

'@auth0/auth0-spa-js': node_modules/@auth0/auth0-spa-js/dist/auth0-spa-js.production.legacy.js

image

image

looking for the function getTokenSilently in auth0-spa-js.production.js exists, but in auth0-spa-js.production.legacy.js it does not exist

 "@auth0/auth0-spa-js": "^1.0.2",

Unable to call getTokenSilently concurrently

Hi!

I'm having an error in the console when creating the Auth0 client using createAuth0Client().

The error is the following:

> ERROR TypeError: Cannot read property 'close' of undefined
    at o (auth0-spa-js.production.js:formatted:1)
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (auth0-spa-js.production.js:formatted:1)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)
    at invokeTask (zone-evergreen.js:1603)
    at globalZoneAwareCallback (zone-evergreen.js:1640)

On the beautyfied production code, the error points to this line:

o = function(i) {
  // Below is the culprit, apparently, 'i.source' is undefined
  i.origin == m && i.data && "authorization_response" === i.data.type && (i.source.close(),
  i.data.response.error ? t(i.data.response) : e(i.data.response),
  clearTimeout(n),
  window.removeEventListener("message", o, !1),
  window.document.body.removeChild(r))
};

And the code that's calling the createAuth0Client() function is this one (pretty much the exact same as the Angular Login Tutorial):

// This is a method of my AuthService
async getAuth0Client(): Promise<Auth0Client> {
  if (!this.auth0Client) {
    console.log("AuthService - generating new Auth0Client");
    this.auth0Client = await createAuth0Client(environment.auth0);
    console.log("AuthService - new Auth0Client", this.auth0Client);

    // Provide the current value of isAuthenticated
    this.isAuthenticated.next(await this.auth0Client.isAuthenticated());

    // Whenever isAuthenticated changes, provide the current value of `getUser`
    this.isAuthenticated
      .subscribe(async isAuthenticated => await this.updateUserProfile(isAuthenticated));
  }
  return this.auth0Client;
}

Note that this error does not prevent the client to be effectively created and functionning. But it's still an unwanted error 😄

Also, some other people seem to have the same kind of issue, see this thread in the Auth0 Community Forums

`createAuth0Client` being async is awkward

Hey 👋

After switching from auth0-js to this package, I wanted to share a piece of feedback. But before I do, let me just say: This package is way simpler to use and understand. Great work!

One thing that is kind of awkward, however, is createAuth0Client being async. And maybe that's because of how I've integrated it into my SPA, but I don't think it's that weird. Let me explain.

I call createAuth0Client in a standalone file that I import where needed:

import createAuth0Client from '@auth0/auth0-spa-js'

export default createAuth0Client({
  // My config...
})

When I import it, it looks something like this:

import auth0Client from './auth0_client'

async function main () {
  const auth0 = await auth0Client

  // Do something with `auth0`...
}

That just feels kind of weird to have to await for the client. I get that you're calling getTokenSilently automatically if the user is authenticated – which is great – but since most (all?) of the other Auth0Client functions return a Promise already, couldn't you re-work it to make (and cache) that call in the constructor, and then await it in the other functions?

I realize that's a major version-type change. In the interim, maybe accept an argument to createAuth0Client that skips the call to getTokenSilently and returns the client right away? Or make it easy for developers to import Auth0Client directly?

How should my API verify this?

I can't find it now, but the original doc/guide I was using (from Auth0) said to use node-jsonwebtoken to verify the access token in the auth header. But the token isn't JWT, so I'm not really sure how to verify a user when they hit the API or how to associate that user with a DB record.

I got the login working on the fronted, but yea, I'm stuck on where to go from there. Sorry if dumb question, just a bit confused.

Unhandled Rejection (Error): Invalid State

I am calling auth0 using the methods provided in react-auth0-wrapper.js. Sporadically I am receiving the following error when I try to login:
IMG-9801
Documentation online says that it's possibly a caching problem, but the documentation is wordpress-plugin-specific. Anyone know what's going on here?
Thanks!

isAuthenticated is undefined after reload

So i tried to make things work with the described example from the react wrapper, also managed to make things work. The problem we have right now is when reloading the app the isAuthenticated is always undefined. We wrapped the Code inside a AppContext wich provides these things for other components and than loads an AuthenticatedApp or UnauthenticatedApp. When flushing the cache and reload the whole Application everything works, but after hitting reload again the isAuthenticated is always undefined. Maybe someone is having the similiar issues.

Code for App:

const loadAuthenticatedApp = () => import('./authenticated-app');
const AuthenticatedApp = React.lazy(loadAuthenticatedApp);
const UnauthenticatedApp = React.lazy(() => import('./unauthenticated-app'));

interface IPrivateApp {
  path?: string;
}

const App: React.FC<IPrivateApp> = ({ path, ...rest }) => {
  const { isAuthenticated, loginWithRedirect } = useAuth0();

  React.useEffect(() => {
    const fn = async () => {
      console.log(`AUTH STATUS`, isAuthenticated);
      if (isAuthenticated === false) {
        await loginWithRedirect({
          appState: { targetUrl: path },
          redirect_uri: '',
        });
      }
    };
    fn();
  }, [isAuthenticated, loginWithRedirect, path]);

  // React.useEffect(() => {
  //   loadAuthenticatedApp();
  // }, []);

  return (
    <Suspense fallback={<CircularProgress />}>
      {isAuthenticated ? <AuthenticatedApp {...rest} /> : <UnauthenticatedApp />}
    </Suspense>
  );
};

export default App;

And Code for the Provider:

import React, { useState, useEffect, useContext, useLayoutEffect } from 'react';
import createAuth0Client from '@auth0/auth0-spa-js';
import Auth0Client from '@auth0/auth0-spa-js/dist/typings/Auth0Client';

interface Auth0Context {
  isAuthenticated: boolean;
  user: any;
  loading: boolean;
  popupOpen: boolean;
  loginWithPopup(options: PopupLoginOptions): Promise<void>;
  handleRedirectCallback(): Promise<RedirectLoginResult>;
  getIdTokenClaims(o?: getIdTokenClaimsOptions): Promise<IdToken>;
  loginWithRedirect(o: RedirectLoginOptions): Promise<void>;
  getTokenSilently(o?: GetTokenSilentlyOptions): Promise<string | undefined>;
  getTokenWithPopup(o?: GetTokenWithPopupOptions): Promise<string | undefined>;
  logout(o?: LogoutOptions): void;
}
interface Auth0ProviderOptions {
  children: React.ReactElement;
  onRedirectCallback?(result: RedirectLoginResult): void;
}

const DEFAULT_REDIRECT_CALLBACK = () => window.history.replaceState({}, document.title, window.location.pathname);

export const Auth0Context = React.createContext<Auth0Context | null>(null);
export const useAuth0 = () => useContext(Auth0Context)!;
export const Auth0Provider = ({
  children,
  onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
  ...initOptions
}: Auth0ProviderOptions & Auth0ClientOptions) => {
  const [isAuthenticated, setIsAuthenticated] = useState();
  const [user, setUser] = useState();
  const [auth0Client, setAuth0] = useState<Auth0Client>();
  const [loading, setLoading] = useState(true);
  const [popupOpen, setPopupOpen] = useState(false);

  useEffect(() => {
    const initAuth0 = async () => {
      const auth0FromHook = await createAuth0Client(initOptions);
      console.log(`SET AUTH0`);
      setAuth0(auth0FromHook);

      if (window.location.search.includes('?code=')) {
        const { appState } = await auth0FromHook.handleRedirectCallback();
        onRedirectCallback(appState);
      }

      const isAuthenticated = await auth0FromHook.isAuthenticated();

      setIsAuthenticated(isAuthenticated);

      if (isAuthenticated) {
        const user = await auth0FromHook.getUser();
        setUser(user);
      }

      setLoading(false);
    };
    initAuth0();
    // eslint-disable-next-line
  }, []);

  const loginWithPopup = async (o: PopupLoginOptions) => {
    setPopupOpen(true);
    try {
      // non null assertion operator - expression to tell the compiler
      // that this could not be null or undefined
      // READ MORE: https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#non-null-assertion-operator
      await auth0Client!.loginWithPopup(o);
    } catch (error) {
      console.error(error);
    } finally {
      setPopupOpen(false);
    }
    const user = await auth0Client!.getUser();
    setUser(user);
    setIsAuthenticated(true);
  };

  const handleRedirectCallback = async () => {
    setLoading(true);
    const result = await auth0Client!.handleRedirectCallback();
    const user = await auth0Client!.getUser();
    setLoading(false);
    setIsAuthenticated(true);
    setUser(user);
    return result;
  };
  return (
    <Auth0Context.Provider
      value={{
        isAuthenticated,
        user,
        loading,
        popupOpen,
        loginWithPopup,
        handleRedirectCallback,
        getIdTokenClaims: (o: getIdTokenClaimsOptions | undefined) => auth0Client!.getIdTokenClaims(o),
        loginWithRedirect: (o: RedirectLoginOptions) => auth0Client!.loginWithRedirect(o),
        getTokenSilently: (o: GetTokenSilentlyOptions | undefined) => auth0Client!.getTokenSilently(o),
        getTokenWithPopup: (o: GetTokenWithPopupOptions | undefined) => auth0Client!.getTokenWithPopup(o),
        logout: (o: LogoutOptions | undefined) => auth0Client!.logout(o),
      }}
    >
      {children}
    </Auth0Context.Provider>
  );
};

And the index.tsx:

render(
  <ApolloProvider client={ApolloClient}>
    <Router history={history}>
      <AppProvider>
        <App />
      </AppProvider>
    </Router>
  </ApolloProvider>,
  document.getElementById('root') as HTMLElement,
);

auth0_spa_js_1.default is not a function

Hi, I'm trying to use the auth0 library in my project but I'm getting an error:

ts_scripts.js?v=1563805379409:34261 ERROR Error: Uncaught (in promise): TypeError: auth0_spa_js_1.default is not a function
TypeError: auth0_spa_js_1.default is not a function

I've seen some similiar issues, #60, #45, but their setups are a bit different and I've tried the suggested tsconfig fixes and I couldn't get them to work.

My project uses a setup similar to the angular-bazel-example, so I've created a repro of the problem using it. Steps are below.

cd /tmp
git clone https://github.com/Dig-Doug/angular-bazel-example.git
cd angular-bazel-example
git checkout 8fa48dc1b977c435178aa5bfc1f9d601ed15f5b7
yarn install
npx bazel run //src:devserver

# It should say "Server listening on XXX"

The auth service from the example is in src/app/auth/ and I've tried to use the service in src/app.component.ts.

When you connect to the local server, the page will load and lots of messages will be printed to the console. Make sure you scroll to the top, the error message is there.

I think the problem has something to do with how the auth0 library is being exported or imported. Looking at the generated code, auth.service.js (note JS), it tries to access the library with:

this.auth0Client = yield auth0_spa_js_1.default(this.config);

In my main project I use lots of other 3rd party libraries, e.g. immutable, three, without issue so it's not an issue with loading libraries in general.

Please let me know if you need any more info.

Thanks!

"await createAuth0Client" takes one minute to finish

Hello, been following the new documentation for Angular and i am finding that when i get to the this.auth0Client = await createAuth0Client(this.config); it awaits for near exactly 60 seconds, which is an issue if the user clicks the login button before that and gets the following error in the console.

Error: "Uncaught (in promise): TypeError: this.auth0Client is undefined

My code is exactly the same as what's provided in the documentation.

Any ideas?

Question: RBAC rules / auth0Client.getPermissionScopes()

The examples of this library in conjunction with roles and permissions (via Authorization Extension) utilise a rules file, which involves duplication of data which the extension already exists.
When using auth-js there is a method called getPermissionScopes which returns the same content as what the rules file contains.
Is there any plans to implement a similar method to get the information required, rather than duplication of the permissions and scopes please?

...or any additional information / best practises on how to implement this would be appreciated

Polyfills needed for IE 11?

Hey 👋

I have a Vue CLI app that I've adding this package to via npm. I have it all working in modern browsers, but IE 11 throws a number of errors related to missing features (i.e., String.prototype.startsWith).

I could be totally off here, but it looks like dist/auth0-spa-js.production.js is built to be ES5 compatible, and work in IE 11?

If not, my follow-up question: What are the polyfills this package needs for IE 11?

Vue CLI recommends either explicitly including the polyfills needed (which I've done with other dependencies), or just including all polyfills for your target browsers. I'd rather not include all polyfills if possible.

Specify response type

He guys.

Is there a way to specify response type for an Auth0Client? As I can see response type is not part of Auth0ClientOptions.

How to integrate this into NextJs app?

I followed QuickStart to integrate this into my NextJs application. But got this error message:

ReferenceError: window is not defined

In my index.js:

import React, { Component } from "react";
import Home from './home'
import { Auth0Provider } from "../services/auth0";
import config from "../services/auth_config.json";

// A function that routes the user to the right place
// after login
const onRedirectCallback = appState => {
  window.history.replaceState(
    {},
    document.title,
    appState && appState.targetUrl
      ? appState.targetUrl
      : window.location.pathname
  );
};

class Index extends Component {

  render() {
    return (
      <Auth0Provider
        domain={config.domain}
        client_id={config.clientId}
        redirect_uri={window.location.origin}
        onRedirectCallback={onRedirectCallback}
      >
        <Home/>
      </Auth0Provider>
    );
  }
}

export default Index;

Any idea? Thanks.

Linking Account Help

Good work so far on this package!

I'm looking at how to authenticate an account using this package without affecting the currently logged in account such that I can trigger the accounts to be linked.

Example:
I have account A logged in using email/password and they want to click a button to authenticate a social network account B but does not want the app to be logged into that social network account.

Am I correct thinking that:

import createAuth0Client from '@auth/auth0-spa-js';

const accountAAuth0 = await createAuth0Client({ domain: 'xxx', client_id: 'yyy' });
await accountAAuth0.loginWithPopup();
const accountAUser = await accountAAuth0.getUser();

const accountBAuth0 = await createAuth0Client({ domain: 'xxx', client_id: 'yyy' });
await accountBAuth0.loginWithPopup();
const accountBUser = await accountBAuth0.getUser();

const accountAUserCopy = await accountAAuth0.getUser();

const worked = (
    accountAUserCopy.sub === accountAUser.sub
    && accountAUserCopy.sub !== accountBUser.sub
);

Is there a way to do this using redirect logins as well?

Question - auth0-spa-js vs auth0-js

What's the difference between auth0-spa-js and auth0-js?

I was integrating using auth0-js and recently looked at React samples to see that it was completely different from before and now uses auth0-spa-js instead of auth0-js.

Should I switch over to auth0-spa-js from auth0-js?

TypeError: Cannot read property 'loginWithRedirect' of undefined

Hey guys,
I've been switching the use the new auth0 login with hooks, when I try to do something very similar to the example, I keep encountering the following error:

TypeError: Cannot read property 'loginWithRedirect' of undefined

It appears that auth0Client is never getting set, so I'm never able to call loginWithRedirect on it. My credentials appear to be correct, and I've been able to login previously with them, so I'm wondering why that is.

My code:

function Home(props) {
    const [value, setValue] = useState("");
    const { isAuthenticated, loginWithRedirect, logout } = useAuth0();
    const { sessionSubmitted, setSessionSubmitted } = useState(false);

    function handleChange(event) {
        setValue(event.target.value);
    }

    function handleSessionSubmit() {
        console.log("we are handling session submit");
        console.log(value);

        props.history.push({
            pathname: "/session",
            search:
                "?" +
                new URLSearchParams({
                    sessionId: value
                }).toString(),
            state: {
                sessionId: value
            }
        });
    }

    return (
        <div class="Home">
            {" "}
            <div className="bar">
                <AppBar
                    position="static"
                    style={{ background: "transparent", boxShadow: "none" }}
                >
                    <Toolbar>
                        <div className="title">
                            <Typography variant="title"> Frindle </Typography>{" "}
                        </div>{" "}
                        <Button onClick={() => loginWithRedirect({})}>
                            {" "}
                            Sign Up{" "}
                        </Button>{" "}
                        <Button onClick={() => loginWithRedirect({})}>
                            {" "}
                            Login{" "}
                        </Button>{" "}
                    </Toolbar>{" "}
                </AppBar>{" "}
            </div>{" "}
            <div className="sessionForm">
                <form onSubmit={handleSessionSubmit}>
                    <div className="text">
                        <TextField
                            name="session"
                            label="Session ID"
                            value={value}
                            onChange={handleChange}
                            margin="normal"
                            variant="outlined"
                        />
                    </div>{" "}
                    <div className="button">
                        <Button
                            type="submit"
                            color="primary"
                            variant="outlined"
                            className="button"
                        >
                            Submit{" "}
                        </Button>{" "}
                    </div>{" "}
                </form>{" "}
            </div>{" "}
        </div>
    );
}

export default withRouter(Home);

Typescript example

Hello! I was using the old quickstart for auth0-js until today it seems the docs have swapped over to the new auth0-spa-js ones -- no problem.

I was wondering if you had any plans to release an example for the spa module in typescript.

Thanks!

User information encoding seems to be lost

Not sure if that is a correct place. It seems that at some point the encoding of the user information is being lost. Not sure if that is library specific, but I've noticed that on my profile page while using auth0-samples/auth0-spa-js-angular-samples locally.

Here is GitHub SDK call:

curl https://api.github.com/users/peterblazejewicz

returning information:

"name": "Piotr Błażejewicz (Peter Blazejewicz)",
"company": ...

while the library keeps information as the:

{
  "name": "Piotr B�ażejewicz (Peter Blazejewicz)",
  "updated_at": ...
}

Thanks!

Please provide more in depth examples... getTokenSilently - react...

For me it"s hard to understand what's happening inside this stuff. So would be great for better examples. Everytime reloading/hot reload while developing, the app asks for login, that sucks alot. Even like described that it will automagically check with getTokenSilently is not happening. Don"t know why. But more detailed explanations would be great.

Configure or Handle Timeout on Popup Authentication

When using loginWithPopup:

    let token;
    try {
      token = await auth0Client.getTokenWithPopup(params);
    } catch (error) {
      console.error(error);
    }

An issue arrises that when an error occurs such as leaving the window open until it times out there is not a recourse to shut the popup window, possibly this should be a parameter with the getTokenWithPopup where a parameter such as closePopupOnError or otherwise would exist. We should also likely be able to control the timeouts associated with this rather than the hard coding to 30s inside of the util script.

This is a fairly large blocker for us but I am not certain how to handle this other than forking the current code and re-integrating it that way.

Export TypeScript types

Hi there,

I'm trying to integrate Auth0 into my SPA and I want to augment the react-auth0-spa sample code with better typing information (in this case using JSDoc in a plain JS project in VSCode) and it would be really helpful if Auth0Client and Auth0ClientOptions types were exported out of this package's typescript definition files (there might be other types that could be useful as well, but the two aforementioned ones are necessary to correctly type the interface of the react hook).

That way I could write something like

/** @typedef { import("@auth0/auth0-spa-js").Auth0Client } */
/** @type { [Auth0Client, (Auth0Client) => void ] } */
const [auth0Client, setAuth0] = useState();

See the Typescript JSDoc support documentation for details on the type syntax.

Auth state is not persisted in ClientStorage

Description of the problem

Every time page is refreshed, session is lost and user need to re-authenticate.

Proposed solution

In index.ts, allow user to ignoreCache or not by passing option :

await auth0.getTokenSilently({
      audience: options.audience,
      scope: options.scope,
      ignoreCache: options.ignoreCache // currently hard coded  to  true
    });

If this suggestion makes sense, i can open a pull request for it, let me know !

Question: what is the use of 'auth0.is.authenticated' cookie

Hi,

I was questioning myself about the use of 'auth0.is.authenticated' cookie as it has been confusing to me (I searched for an answer on other issues but could not find one, sorry if I missed it).

What seem strange to me is that, when creating an auth0 client, presence of this cookie is checked before we try to authenticate silently.
Here is the line https://github.com/auth0/auth0-spa-js/blob/master/src/index.ts#L11

What exactly is the purpose of such check ? (and thus the purpose of such cookie).

My use case is: I have an (quite old) angularjs app which directly uses auth0-js and a new react app which uses auth0-spa-js. If I login on my angularjs app, then navigate to my react app, since the 'auth0.is.authenticated' cookie is not present, my react app won't try silent authentication and I won't be logged in.
Though I could myself trigger a silent auth when my auth0 client finished loading, I would expect the lib to always do it whatever the cookie is because there might be an auth0 session existing for me.

Please enlighten me on this, did I miss something ?
Cheers

How to do token renewal

On the old auth0-js tutorial, you could renew the token until the user session expires. How would one implement it in the auth0-spa-js?

Grant type 'authorization_code' not allowed for the client.

Hi!

I'm pretty new to this auth topic. I followed along the react tutorial. But when I click on loginwithredirect I get immediately this error 'Grant type 'authorization_code' not allowed for the client.'. I need to say that I'm using react with typescript.

I've copied the wrapper from @luisrudge in his answer here.

My config was working with the old js library though. Any suggestions what I did wrong?

Thanks

Can't resolve '@auth0/auth0-spa-js/dist/typings/Auth0Client'

Hi,

I was reading the online documentation on how to use @auth0-spa-js with angular on the official website. So I installed it.

but have been getting this error:

ERROR in ./src/app/services/auth.service.ts
Module not found: Error: Can't resolve '@auth0/auth0-spa-js/dist/typings/Auth0Client' in

I'm not sure why this is happening? so I tried your sample project on GitHub. surprisingly enough it works.

I'm not sure what to do now.

My package.json content:

"dependencies": {},
"devDependencies": {
"@angular-devkit/schematics": "^8.1.1",
"@angular/animations": "^8.1.1",
"@angular/cdk": "^8.0.2",
"@angular/cli": "~8.0.2",
"@angular/common": "^8.1.1",
"@angular/compiler": "^8.1.1",
"@angular/core": "^8.1.1",
"@angular/flex-layout": "^8.0.0-beta.26",
"@angular/forms": "^8.1.1",
"@angular/material": "^8.0.2",
"@angular/platform-browser": "^8.1.1",
"@angular/platform-browser-dynamic": "^8.1.1",
"@angular/router": "^8.1.1",
"@auth0/auth0-spa-js": "^1.0.2",
"@ngx-progressbar/core": "^5.0.1",
"@ngx-progressbar/router": "^5.0.1",
"@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0",
"angular-webstorage-service": "^1.0.2",
"bootstrap": "^3.4.1",
"chart.js": "^2.7.2",
"chartjs-plugin-zoom": "^0.7.2",
"classlist.js": "^1.1.20150312",
"core-js": "^3.1.4",
"font-awesome": "^4.7.0",
"hammerjs": "^2.0.8",
"mathjs": "^6.0.3",
"ng2-charts": "^2.3.0",
"ngx-clipboard": "^12.2.0",
"rxjs": "^6.2.1",
"rxjs-compat": "6.5.2",
"web-animations-js": "^2.3.1",
"zone.js": "^0.9.1",
"@angular-devkit/build-angular": "^0.801.1",
"@angular/compiler-cli": "^8.1.1",
"@angular/language-service": "^8.1.1",
"@types/jasmine": "^3.3.13",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~12.6.2",
"codelyzer": "~5.1.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^2.0.5",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"protractor": "^5.3.2",
"ts-node": "~8.3.0",
"tslint": "~5.18.0",
"typescript": "^3.4.5"

does somebody know about this issue?
please help

React: Apollo hooks

Hi, how would the React wrapper work in combination with @apollo/hooks?

At some point in my application, I would like to add an additional header with my access token if the user decided to log in. Some graphql queries should be available when the user isn't logged in.
So I have a scenario where I want to add the header only at a later point.

Nickname, Email, and Picture

Using the old SDK, when I called my server API with my access token, on the server I would also have a user object with nickname, email, and picture. After updating to this library, that data is no longer available. My server code relies on this. Is there something wrong with my configuration? A bug in this library? A breaking change that no longer makes this info available?

Any assistance would be great.

How does one actually get the JWT?

I have created the SPA and I've created an API. When I use the example and call the handleRedirect function, I see the call go out to the /token endpoint which does return an id_token. That said, I don't see any way to actually get that token and save it to local storage.

I copied it and used it directly in Postman to call an API, and I'm getting Expected {different audience} and auth does not work. What am I missing here?

Also how does the API know that the SPA's client I created is authorized to access it? Do I need a service to use the secret key to generate a token or something?

Invalid algorithm error

Hi, I've just tried to run react login example from github with my domain and clientId and receive the following error.
image

Do you know how it can be fixed?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.