diff --git a/apps/sensenet/cypress.json b/apps/sensenet/cypress.json
index 36b1d1e5c..3ece198d7 100644
--- a/apps/sensenet/cypress.json
+++ b/apps/sensenet/cypress.json
@@ -7,7 +7,7 @@
"identityServer": "https://is.demo.sensenet.com",
"users": {
"admin": {
- "clientId": "businesscat",
+ "clientId": "KxkgOTAxLLCicUx7",
"clientSecret": "",
"id": "/Root/IMS/Public('businesscat')"
},
diff --git a/apps/sensenet/cypress/support/commands.js b/apps/sensenet/cypress/support/commands.js
index e02b5da40..675df2b77 100644
--- a/apps/sensenet/cypress/support/commands.js
+++ b/apps/sensenet/cypress/support/commands.js
@@ -1,4 +1,6 @@
import 'cypress-file-upload'
+import { codeLogin } from '@sensenet/authentication-oidc-react'
+
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
@@ -35,34 +37,13 @@ Cypress.on('uncaught:exception', (err) => {
Cypress.Commands.add('login', (userType = 'admin') => {
const user = Cypress.env('users')[userType]
-
- const configuration = {
- client_id: user.clientId,
- client_secret: Cypress.env(`secret_${userType}`) || user.clientSecret,
- grant_type: 'client_credentials',
- scope: encodeURIComponent('sensenet'),
- }
-
- const requestBody = Object.keys(configuration).reduce((acc, current, idx) => {
- return `${acc}${current}=${configuration[current]}${idx === Object.keys(configuration).length - 1 ? '' : '&'}`
- }, '')
-
- cy.request({
- url: `${Cypress.env('identityServer')}/connect/token`,
- method: 'POST',
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
- body: requestBody,
- }).then((resp) => {
- const oidcUser = resp.body
-
- oidcUser.profile = {
- sub: user.id,
- }
-
- window.sessionStorage.setItem(
- `oidc.user:${Cypress.env('identityServer')}:11V28Add7IaP1iFw`,
- JSON.stringify(oidcUser),
- )
+ codeLogin({
+ clientId: user.clientId,
+ clientSecret: Cypress.env(`secret_${userType}`) || user.clientSecret,
+ identityServerUrl: Cypress.env('identityServer'),
+ appId: '11V28Add7IaP1iFw',
+ userId: user.id,
+ fetchMethod: (url, options) => cy.request({ url, ...options }),
})
})
diff --git a/examples/sn-react-browser/.env b/examples/sn-react-browser/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-browser/.env
+++ b/examples/sn-react-browser/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-browser/src/components/app-providers.tsx b/examples/sn-react-browser/src/components/app-providers.tsx
index e0415c375..d87b30ddb 100644
--- a/examples/sn-react-browser/src/components/app-providers.tsx
+++ b/examples/sn-react-browser/src/components/app-providers.tsx
@@ -1,40 +1,35 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-browser/src/components/login-form.tsx b/examples/sn-react-browser/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-browser/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-browser/src/components/navbar.tsx b/examples/sn-react-browser/src/components/navbar.tsx
index aaa234d00..87fc16402 100644
--- a/examples/sn-react-browser/src/components/navbar.tsx
+++ b/examples/sn-react-browser/src/components/navbar.tsx
@@ -1,5 +1,4 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { AppBar, Button, Toolbar, Typography } from '@material-ui/core'
+import { AppBar, Toolbar, Typography } from '@material-ui/core'
import { createStyles, makeStyles } from '@material-ui/core/styles'
import React from 'react'
@@ -17,7 +16,6 @@ const useStyles = makeStyles(() =>
* Navbar component
*/
export const NavBarComponent: React.FunctionComponent = () => {
- const { logout } = useOidcAuthentication()
const classes = useStyles()
return (
@@ -27,9 +25,6 @@ export const NavBarComponent: React.FunctionComponent = () => {
Document Browser
-
diff --git a/examples/sn-react-browser/src/configuration.ts b/examples/sn-react-browser/src/configuration.ts
index 62e7aea02..1ad42a02d 100644
--- a/examples/sn-react-browser/src/configuration.ts
+++ b/examples/sn-react-browser/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
-export const repositoryUrl = 'https://dev.demo.sensenet.com/'
+export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-browser/test/navbar.test.tsx b/examples/sn-react-browser/test/navbar.test.tsx
deleted file mode 100644
index e7d75eda7..000000000
--- a/examples/sn-react-browser/test/navbar.test.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-/* eslint-disable react/display-name */
-
-import Button from '@material-ui/core/Button'
-import { mount } from 'enzyme'
-import React, { PropsWithChildren } from 'react'
-import { AppProviders } from '../src/components/app-providers'
-import { NavBarComponent } from '../src/components/navbar'
-
-const logout = jest.fn()
-jest.mock('@sensenet/authentication-oidc-react', () => ({
- useOidcAuthentication: () => ({ oidcUser: { access_token: 'token' }, logout }),
- AuthenticationProvider: ({ children }: PropsWithChildren<{}>) => <>{children}>,
-}))
-
-const NavBar = () => (
-
-
-
-)
-
-describe('The navbar instance', () => {
- it('should logout the user correctly', () => {
- const wrapper = mount()
-
- wrapper.find(Button).simulate('click')
- expect(logout).toBeCalled()
- })
-})
diff --git a/examples/sn-react-calendar/.env b/examples/sn-react-calendar/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-calendar/.env
+++ b/examples/sn-react-calendar/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-calendar/src/components/app-providers.tsx b/examples/sn-react-calendar/src/components/app-providers.tsx
index e0415c375..d87b30ddb 100644
--- a/examples/sn-react-calendar/src/components/app-providers.tsx
+++ b/examples/sn-react-calendar/src/components/app-providers.tsx
@@ -1,40 +1,35 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-calendar/src/components/login-form.tsx b/examples/sn-react-calendar/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-calendar/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-calendar/src/components/navbar.tsx b/examples/sn-react-calendar/src/components/navbar.tsx
index 7cd9b3a51..e7db0a12a 100644
--- a/examples/sn-react-calendar/src/components/navbar.tsx
+++ b/examples/sn-react-calendar/src/components/navbar.tsx
@@ -1,5 +1,4 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { AppBar, Button, Toolbar, Typography } from '@material-ui/core'
+import { AppBar, Toolbar, Typography } from '@material-ui/core'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import React from 'react'
@@ -17,7 +16,6 @@ const useStyles = makeStyles((theme: Theme) =>
* Navbar component
*/
export const NavBarComponent: React.FunctionComponent = () => {
- const { logout } = useOidcAuthentication()
const classes = useStyles()
return (
@@ -27,9 +25,6 @@ export const NavBarComponent: React.FunctionComponent = () => {
Calendar
-
diff --git a/examples/sn-react-calendar/src/configuration.ts b/examples/sn-react-calendar/src/configuration.ts
index 62e7aea02..1ad42a02d 100644
--- a/examples/sn-react-calendar/src/configuration.ts
+++ b/examples/sn-react-calendar/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
-export const repositoryUrl = 'https://dev.demo.sensenet.com/'
+export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-imagegallery/.env b/examples/sn-react-imagegallery/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-imagegallery/.env
+++ b/examples/sn-react-imagegallery/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-imagegallery/src/components/app-providers.tsx b/examples/sn-react-imagegallery/src/components/app-providers.tsx
index 6d9b29958..0b9cff4e1 100644
--- a/examples/sn-react-imagegallery/src/components/app-providers.tsx
+++ b/examples/sn-react-imagegallery/src/components/app-providers.tsx
@@ -1,44 +1,39 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
import { MuiThemeProvider } from '@material-ui/core'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
import { theme } from '../theme'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-imagegallery/src/components/login-form.tsx b/examples/sn-react-imagegallery/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-imagegallery/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-imagegallery/src/configuration.ts b/examples/sn-react-imagegallery/src/configuration.ts
index 337c08573..1ad42a02d 100644
--- a/examples/sn-react-imagegallery/src/configuration.ts
+++ b/examples/sn-react-imagegallery/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-memoapp/.env b/examples/sn-react-memoapp/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-memoapp/.env
+++ b/examples/sn-react-memoapp/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-memoapp/src/components/app-providers.tsx b/examples/sn-react-memoapp/src/components/app-providers.tsx
index e0415c375..d87b30ddb 100644
--- a/examples/sn-react-memoapp/src/components/app-providers.tsx
+++ b/examples/sn-react-memoapp/src/components/app-providers.tsx
@@ -1,40 +1,35 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-memoapp/src/components/login-form.tsx b/examples/sn-react-memoapp/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-memoapp/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-memoapp/src/components/navbar.tsx b/examples/sn-react-memoapp/src/components/navbar.tsx
index a49340112..232f08a0b 100644
--- a/examples/sn-react-memoapp/src/components/navbar.tsx
+++ b/examples/sn-react-memoapp/src/components/navbar.tsx
@@ -1,5 +1,4 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { AppBar, Button, Toolbar, Typography } from '@material-ui/core'
+import { AppBar, Toolbar, Typography } from '@material-ui/core'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import React from 'react'
@@ -18,7 +17,6 @@ const useStyles = makeStyles((theme: Theme) =>
* Navbar component
*/
export const NavBarComponent: React.FunctionComponent = () => {
- const { logout } = useOidcAuthentication()
const classes = useStyles()
return (
@@ -28,9 +26,6 @@ export const NavBarComponent: React.FunctionComponent = () => {
Memo application
-
diff --git a/examples/sn-react-memoapp/src/configuration.ts b/examples/sn-react-memoapp/src/configuration.ts
index 62e7aea02..1ad42a02d 100644
--- a/examples/sn-react-memoapp/src/configuration.ts
+++ b/examples/sn-react-memoapp/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
-export const repositoryUrl = 'https://dev.demo.sensenet.com/'
+export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-tasklist/.env b/examples/sn-react-tasklist/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-tasklist/.env
+++ b/examples/sn-react-tasklist/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-tasklist/src/components/app-providers.tsx b/examples/sn-react-tasklist/src/components/app-providers.tsx
index e0415c375..d87b30ddb 100644
--- a/examples/sn-react-tasklist/src/components/app-providers.tsx
+++ b/examples/sn-react-tasklist/src/components/app-providers.tsx
@@ -1,40 +1,35 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-tasklist/src/components/login-form.tsx b/examples/sn-react-tasklist/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-tasklist/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-tasklist/src/configuration.ts b/examples/sn-react-tasklist/src/configuration.ts
index 62e7aea02..1ad42a02d 100644
--- a/examples/sn-react-tasklist/src/configuration.ts
+++ b/examples/sn-react-tasklist/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
-export const repositoryUrl = 'https://dev.demo.sensenet.com/'
+export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-typescript-boilerplate/tsconfig.json b/examples/sn-react-typescript-boilerplate/tsconfig.json
index 3a301d5c9..663219d18 100644
--- a/examples/sn-react-typescript-boilerplate/tsconfig.json
+++ b/examples/sn-react-typescript-boilerplate/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@@ -13,7 +17,11 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
- "jsx": "react"
+ "jsx": "react-jsx",
+ "noFallthroughCasesInSwitch": true
},
- "include": ["src", "../../typings"]
+ "include": [
+ "src",
+ "../../typings"
+ ]
}
diff --git a/examples/sn-react-usersearch/.env b/examples/sn-react-usersearch/.env
index 46af40f4c..6f7d63310 100644
--- a/examples/sn-react-usersearch/.env
+++ b/examples/sn-react-usersearch/.env
@@ -1,2 +1,4 @@
SKIP_PREFLIGHT_CHECK=true
FAST_REFRESH=false
+REACT_APP_CLIENT_ID=KxkgOTAxLLCicUx7
+REACT_APP_CLIENT_SECRET=
diff --git a/examples/sn-react-usersearch/src/app.tsx b/examples/sn-react-usersearch/src/app.tsx
index 0638e7c7e..e500e7477 100644
--- a/examples/sn-react-usersearch/src/app.tsx
+++ b/examples/sn-react-usersearch/src/app.tsx
@@ -17,8 +17,6 @@ import UserSearch from './components/user-search'
* The main entry point of your app. You can start h@cking from here ;)
*/
export const App: React.FunctionComponent = () => {
- // const usr = useCurrentUser()
- // const repo = useRepository()
return (
diff --git a/examples/sn-react-usersearch/src/components/app-providers.tsx b/examples/sn-react-usersearch/src/components/app-providers.tsx
index e0415c375..d87b30ddb 100644
--- a/examples/sn-react-usersearch/src/components/app-providers.tsx
+++ b/examples/sn-react-usersearch/src/components/app-providers.tsx
@@ -1,40 +1,35 @@
-import { AuthenticationProvider, useOidcAuthentication } from '@sensenet/authentication-oidc-react'
+import { codeLogin, CodeLoginResponse } from '@sensenet/authentication-oidc-react'
import { Repository } from '@sensenet/client-core'
import { RepositoryContext } from '@sensenet/hooks-react'
-import React, { PropsWithChildren } from 'react'
-import { BrowserRouter, useHistory } from 'react-router-dom'
+import React, { PropsWithChildren, useEffect, useState } from 'react'
+import { BrowserRouter } from 'react-router-dom'
import { configuration, repositoryUrl } from '../configuration'
-import { LoginForm } from './login-form'
+import { FullScreenLoader } from './full-screen-loader'
export function AppProviders({ children }: PropsWithChildren<{}>) {
return (
-
- {children}
-
+ {children}
)
}
-export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
- const history = useHistory()
-
- return (
-
- {children}
-
- )
-}
-
export const RepositoryProvider = ({ children }: PropsWithChildren<{}>) => {
- const { oidcUser } = useOidcAuthentication()
+ const [authData, setAuthData] = useState()
+
+ useEffect(() => {
+ ;(async () => {
+ const response = await codeLogin(configuration)
+ setAuthData(response)
+ })()
+ }, [])
- if (!oidcUser) {
- return
+ if (!authData) {
+ return
}
return (
-
+
{children}
)
diff --git a/examples/sn-react-usersearch/src/components/header.tsx b/examples/sn-react-usersearch/src/components/header.tsx
index 194937445..05898cc1b 100644
--- a/examples/sn-react-usersearch/src/components/header.tsx
+++ b/examples/sn-react-usersearch/src/components/header.tsx
@@ -1,13 +1,8 @@
-// start of material imports
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
import AppBar from '@material-ui/core/AppBar'
-import IconButton from '@material-ui/core/IconButton'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import Toolbar from '@material-ui/core/Toolbar'
import Typography from '@material-ui/core/Typography'
-import LogoutIcon from '@material-ui/icons/PowerSettingsNew'
import React from 'react'
-// end of material imports
const useStyles = makeStyles((theme: Theme) =>
createStyles({
@@ -33,7 +28,6 @@ const useStyles = makeStyles((theme: Theme) =>
)
const HeaderPanel = () => {
- const { logout, oidcUser } = useOidcAuthentication()
const classes = useStyles()
return (
@@ -41,16 +35,8 @@ const HeaderPanel = () => {
- {oidcUser?.profile.name}
+ User search
-
-
-
diff --git a/examples/sn-react-usersearch/src/components/login-form.tsx b/examples/sn-react-usersearch/src/components/login-form.tsx
deleted file mode 100644
index 82d50a21e..000000000
--- a/examples/sn-react-usersearch/src/components/login-form.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useOidcAuthentication } from '@sensenet/authentication-oidc-react'
-import { Button, Paper, Typography } from '@material-ui/core'
-import React from 'react'
-import { repositoryUrl } from '../configuration'
-
-export const LoginForm = () => {
- const { login } = useOidcAuthentication()
-
- return (
-
-
- Login to {repositoryUrl}
-
-
-
-
-
-
- )
-}
diff --git a/examples/sn-react-usersearch/src/components/user-search.tsx b/examples/sn-react-usersearch/src/components/user-search.tsx
index ae2bd1049..bb0b245fd 100644
--- a/examples/sn-react-usersearch/src/components/user-search.tsx
+++ b/examples/sn-react-usersearch/src/components/user-search.tsx
@@ -109,7 +109,7 @@ const UserSearchPanel = () => {
const sendRequest = async () => {
const result = await repo.loadCollection({
- path: `/Root/IMS`,
+ path: `/Root/IMS/Public`,
oDataOptions: {
metadata: 'no',
inlinecount: 'allpages',
diff --git a/examples/sn-react-usersearch/src/configuration.ts b/examples/sn-react-usersearch/src/configuration.ts
index 62e7aea02..1ad42a02d 100644
--- a/examples/sn-react-usersearch/src/configuration.ts
+++ b/examples/sn-react-usersearch/src/configuration.ts
@@ -1,14 +1,10 @@
-import { UserManagerSettings } from '@sensenet/authentication-oidc-react'
+import { CodeLoginParams } from '@sensenet/authentication-oidc-react'
-export const repositoryUrl = 'https://dev.demo.sensenet.com/'
+export const repositoryUrl = 'https://dev.demo.sensenet.com'
-export const configuration: UserManagerSettings = {
- client_id: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
- redirect_uri: `${window.location.origin}/authentication/callback`,
- response_type: 'code',
- post_logout_redirect_uri: `${window.location.origin}/`,
- scope: 'openid profile sensenet',
- authority: 'https://is.demo.sensenet.com/',
- silent_redirect_uri: `${window.location.origin}/authentication/silent_callback`,
- extraQueryParams: { snrepo: repositoryUrl },
+export const configuration: CodeLoginParams = {
+ clientId: process.env.REACT_APP_CLIENT_ID ?? '', // businesscat clientId for dev.demo.sensenet.com
+ clientSecret: process.env.REACT_APP_CLIENT_SECRET ?? '',
+ identityServerUrl: 'https://is.demo.sensenet.com',
+ appId: '7cYLChuhJxyGb7BS', //externalSPA clientId for dev.demo.sensenet.com
}
diff --git a/examples/sn-react-usersearch/tsconfig.json b/examples/sn-react-usersearch/tsconfig.json
index 3a301d5c9..663219d18 100644
--- a/examples/sn-react-usersearch/tsconfig.json
+++ b/examples/sn-react-usersearch/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@@ -13,7 +17,11 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
- "jsx": "react"
+ "jsx": "react-jsx",
+ "noFallthroughCasesInSwitch": true
},
- "include": ["src", "../../typings"]
+ "include": [
+ "src",
+ "../../typings"
+ ]
}
diff --git a/packages/sn-authentication-oidc-react/src/code-login.ts b/packages/sn-authentication-oidc-react/src/code-login.ts
new file mode 100644
index 000000000..7b67b7e92
--- /dev/null
+++ b/packages/sn-authentication-oidc-react/src/code-login.ts
@@ -0,0 +1,52 @@
+import { SigninResponse } from 'oidc-client'
+
+export type CodeLoginResponse = Pick
+
+export interface CodeLoginParams {
+ clientId: string
+ clientSecret: string
+ identityServerUrl: string
+ userId?: string | number
+ appId?: string
+ fetchMethod?: WindowOrWorkerGlobalScope['fetch']
+}
+
+export const codeLogin = async ({
+ clientId,
+ clientSecret,
+ identityServerUrl,
+ userId,
+ appId,
+ fetchMethod = window && window.fetch && window.fetch.bind(window),
+}: CodeLoginParams) => {
+ const configuration = {
+ client_id: clientId,
+ client_secret: clientSecret,
+ grant_type: 'client_credentials',
+ scope: encodeURIComponent('sensenet'),
+ }
+
+ const requestBody = Object.entries(configuration).reduce((acc, current, idx) => {
+ return `${acc}${current[0]}=${current[1]}${idx === Object.entries(configuration).length - 1 ? '' : '&'}`
+ }, '')
+
+ const url = `${identityServerUrl}/connect/token`
+ const options = {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ body: requestBody,
+ }
+
+ const response = await fetchMethod(url, options)
+ const authData: CodeLoginResponse = (await response.json?.()) ?? response.body ?? response
+
+ if (userId && authData) {
+ authData.profile = {
+ sub: userId,
+ }
+ }
+
+ appId && window?.sessionStorage?.setItem(`oidc.user:${identityServerUrl}:${appId}`, JSON.stringify(authData))
+
+ return authData
+}
diff --git a/packages/sn-authentication-oidc-react/src/index.ts b/packages/sn-authentication-oidc-react/src/index.ts
index a27a07151..862524963 100644
--- a/packages/sn-authentication-oidc-react/src/index.ts
+++ b/packages/sn-authentication-oidc-react/src/index.ts
@@ -2,4 +2,5 @@ import { UserManager, UserManagerSettings, WebStorageStateStore } from 'oidc-cli
export * from './components/authentication-provider'
export * from './components/oidc-secure'
export * from './use-authentication'
+export * from './code-login'
export { WebStorageStateStore, UserManagerSettings, UserManager }
diff --git a/packages/sn-authentication-oidc-react/test/code-login.test.tsx b/packages/sn-authentication-oidc-react/test/code-login.test.tsx
new file mode 100644
index 000000000..77ecd336b
--- /dev/null
+++ b/packages/sn-authentication-oidc-react/test/code-login.test.tsx
@@ -0,0 +1,47 @@
+import { codeLogin } from '../src/code-login'
+
+declare const global: any
+global.window = {}
+
+describe('CodeLogin', () => {
+ const loginParams = { clientId: 'test', clientSecret: 'test', identityServerUrl: 'https://is.test.com' }
+
+ const mockData = {
+ access_token: 'eyJhbGciOiJSUUclFOZmVmODlYZHhSVVMtNkkdCtqd3QifQ.eyJuYmYiOjE2MTk1Mj4eg7dmeDMJ0aow9ewPqleqdSpHwl',
+ expires_in: 3600,
+ scope: 'sensenet',
+ token_type: 'Bearer',
+ }
+
+ const mockResponse = {
+ ok: true,
+ json: async () => mockData,
+ }
+
+ const fetchMock: any = async () => {
+ return mockResponse
+ }
+
+ it('Should be constructed with a built-in fetch method', () => {
+ global.window.fetch = jest.fn(() => mockResponse)
+ codeLogin(loginParams)
+ expect(global.window.fetch).toBeCalled()
+
+ expect(global.window.fetch).toHaveBeenCalledWith('https://is.test.com/connect/token', {
+ body: 'client_id=test&client_secret=test&grant_type=client_credentials&scope=sensenet',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ method: 'POST',
+ })
+ })
+
+ it('should resolve with a proper response', async () => {
+ const resp = await codeLogin({ ...loginParams, fetchMethod: fetchMock })
+ expect(resp).toEqual(mockData)
+ })
+
+ it('should resolve with userId', async () => {
+ const responseData = { ...mockData, profile: { sub: 1 } }
+ const resp = await codeLogin({ ...loginParams, fetchMethod: fetchMock, userId: 1 })
+ expect(resp).toEqual(responseData)
+ })
+})