Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refresh not working #1253

Open
JoezerSmaniotto opened this issue May 21, 2024 · 2 comments
Open

refresh not working #1253

JoezerSmaniotto opened this issue May 21, 2024 · 2 comments
Labels
question Further information is requested

Comments

@JoezerSmaniotto
Copy link

JoezerSmaniotto commented May 21, 2024

I have a project created by Vite, which is reactjs with typescript, it works, but the refreshToken is not working, could you help me, when I try to add refresh I get a lot of errors.

Here is the project link, if you get an answer, describe it here or make a pull request
https://github.com/JoezerSmaniotto/IdentityServerIs

My project looks like this:

oidcConfig.ts

import { WebStorageStateStore, User } from 'oidc-client-ts';
export const oidcConfig = {
  authority: ENV.AUTHORIT,
  client_id: ENV.CLIENT_ID,
  redirect_uri: "http://localhost:4200/",
  post_logout_redirect_uri: "http://localhost:4200",
  response_type: "code",
  prompt: 'login', // Faz o login sempre acontecer novamente
  scope: "openid robot_signalr_api feeder_subscriber",
  automaticSilentRenew: true,
  //silent_redirect_uri: "http://localhost:4200/silent-renew",
  systemOrigem: 'AAI',
  userStore: new WebStorageStateStore({ store: window.localStorage }), // Adicione esta linha
  onSigninCallback: async (user: User) => {
    if (user) {
      window.history.replaceState({}, document.title, window.location.pathname);
    }
  },

App.tsx

// src/App.tsx
import React, { useEffect } from 'react';
import { useAuth } from 'react-oidc-context';
import AppRoutes from './Routes';

const App: React.FC = () => {
  const auth = useAuth();

  // useEffect(() => {
  //   if (!auth.isLoading && !auth.isAuthenticated) {
  //     auth.signinRedirect();
  //   }
  // }, [auth.isLoading, auth.isAuthenticated, auth]);
  // useEffect(() => {
  //   if (!auth.isLoading && !auth.isAuthenticated && !auth.activeNavigator) {
  //     auth.signinRedirect();
  //   }
  // }, [auth.isLoading, auth.isAuthenticated, auth.activeNavigator, auth]);

  if (auth.isLoading) {
    return <div>Loading...</div>;
  }

  // if (auth.error) {
  //   return <div>Oops... {auth.error.message}</div>;
  // }


  useEffect(() => {
    // the `return` is important - addAccessTokenExpiring() returns a cleanup function
    return auth.events.addAccessTokenExpiring(() => {
      auth.signinSilent();
    })
  }, [auth.events, auth.signinSilent]);

  return (
    <AppRoutes />
  );
};


export default App;

Routes.tsx

// src/Routes.tsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import ProtectedRoute from './components/ProtectedRoute';
import LoginPage from './components/LoginPage';
import PrivatePage from './components/PrivateRoute';

const AppRoutes: React.FC = () => {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        <Route element={<ProtectedRoute />}>
          <Route path="/*" element={<PrivatePage />} />
        </Route>
      </Routes>
    </Router>
  );
};

export default AppRoutes;

ProtectedRoute.tsx

import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { useAuth } from 'react-oidc-context';

const ProtectedRoute: React.FC = () => {
  const auth = useAuth();

  if (auth.isLoading) {
    return <div>Loading...</div>;
  }

  return auth.isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
};

export default ProtectedRoute;

Login.tsx

// src/components/LoginPage.tsx
import React, { useEffect } from 'react';
import { useAuth } from 'react-oidc-context';
import { useNavigate } from 'react-router-dom';

const LoginPage: React.FC = () => {
  const auth = useAuth();
  const navigate = useNavigate();

  useEffect(() => {
    if (auth.isAuthenticated) {
      navigate('/');
    }
  }, [auth])

  return (
    <div>
      <button onClick={() => void auth.signinRedirect()}>Log in</button>
    </div>
  );
};

export default LoginPage;

PrivatePage.tsx

// src/components/PrivatePage.tsx
import React from 'react';
import { useAuth } from 'react-oidc-context';
import { CustomOidcUser } from '../types/OidcUser';


const PrivatePage: React.FC = () => {
  const auth = useAuth();

  const user = auth.user as CustomOidcUser;
  const profile = user?.profile;

  return (
    <div>
      <p>Private Page</p>
      <p>{profile?.Broker}</p>
      <button onClick={() => void auth.removeUser()}>Log out</button>
    </div>
  )
};

export default PrivatePage;

I tried implementing onSigninCallback in oidcConfig.ts on onSigninCallback , as requested here, `You must provide an implementation of onSigninCallback to oidcConfig to remove the payload from the URL upon successful login. Otherwise if you refresh the page and the payload is still there, signinSilent - which handles renewing your token - won't work.

A working implementation is already in the code here.`
https://www.npmjs.com/package/react-oidc-context?activeTab=readme

But there is an error in main.tsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import { AuthProvider } from 'react-oidc-context';
import { oidcConfig } from './oidcConfig';
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <AuthProvider {...oidcConfig}>
    <App />
  </AuthProvider>,

)

Could you help me refresh Token and implement onSigninCallback ?

@pamapa
Copy link
Member

pamapa commented May 23, 2024

When setting automaticSilentRenew: true, the underlying library oidc-client-ts takes care of the renew process, it triggers it and this library will handle the callback.

So either you handle it your own or not...

useEffect(() => {
  // the `return` is important - addAccessTokenExpiring() returns a cleanup function
  return auth.events.addAccessTokenExpiring(() => {
    auth.signinSilent();
 })
}, [auth.events, auth.signinSilent]);

Adding logging like described here https://authts.github.io/oidc-client-ts/#md:logging should allow you to understand the process...

@pamapa pamapa added the question Further information is requested label May 23, 2024
@JoezerSmaniotto
Copy link
Author

JoezerSmaniotto commented May 28, 2024

@pamapa
Following the first option, adding automaticSilentRenew: true, is it necessary to pass any more data such as: Silent_redirect_uri? If so, what would need to be added? Could you explain more clearly?
consider that my oidcConfig is like this.

import { WebStorageStateStore, User } from 'oidc-client-ts';
export const oidcConfig = {
  authority: ENV.AUTHORIT,
  client_id: ENV.CLIENT_ID,
  redirect_uri: "http://localhost:4200/",
  post_logout_redirect_uri: "http://localhost:4200",
  response_type: "code",
  prompt: 'login', // Faz o login sempre acontecer novamente
  scope: "openid robot_signalr_api feeder_subscriber",
  automaticSilentRenew: true,
  //silent_redirect_uri: "http://localhost:4200/silent-renew",
  systemOrigem: 'AAI',
  userStore: new WebStorageStateStore({ store: window.localStorage }), // Adicione esta linha
  onSigninCallback: async (user: User) => {
    if (user) {
      window.history.replaceState({}, document.title, window.location.pathname);
    }
  },

If necessary, please explain what needs to be changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants