@owlmeans/web-oidc-rp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +515 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/auth/plugins/index.d.ts +4 -0
  5. package/build/auth/plugins/index.d.ts.map +1 -0
  6. package/build/auth/plugins/index.js +6 -0
  7. package/build/auth/plugins/index.js.map +1 -0
  8. package/build/auth/plugins/oidc-client.d.ts +3 -0
  9. package/build/auth/plugins/oidc-client.d.ts.map +1 -0
  10. package/build/auth/plugins/oidc-client.js +97 -0
  11. package/build/auth/plugins/oidc-client.js.map +1 -0
  12. package/build/components/dispatcher.d.ts +2 -0
  13. package/build/components/dispatcher.d.ts.map +1 -0
  14. package/build/components/dispatcher.js +58 -0
  15. package/build/components/dispatcher.js.map +1 -0
  16. package/build/components/index.d.ts +2 -0
  17. package/build/components/index.d.ts.map +1 -0
  18. package/build/components/index.js +2 -0
  19. package/build/components/index.js.map +1 -0
  20. package/build/consts.d.ts +7 -0
  21. package/build/consts.d.ts.map +1 -0
  22. package/build/consts.js +8 -0
  23. package/build/consts.js.map +1 -0
  24. package/build/guard.d.ts +6 -0
  25. package/build/guard.d.ts.map +1 -0
  26. package/build/guard.js +18 -0
  27. package/build/guard.js.map +1 -0
  28. package/build/index.d.ts +6 -0
  29. package/build/index.d.ts.map +1 -0
  30. package/build/index.js +5 -0
  31. package/build/index.js.map +1 -0
  32. package/build/service.d.ts +3 -0
  33. package/build/service.d.ts.map +1 -0
  34. package/build/service.js +112 -0
  35. package/build/service.js.map +1 -0
  36. package/build/types.d.ts +25 -0
  37. package/build/types.d.ts.map +1 -0
  38. package/build/types.js +2 -0
  39. package/build/types.js.map +1 -0
  40. package/package.json +60 -0
  41. package/src/auth/plugins/index.ts +8 -0
  42. package/src/auth/plugins/oidc-client.tsx +114 -0
  43. package/src/components/dispatcher.tsx +61 -0
  44. package/src/components/index.ts +2 -0
  45. package/src/consts.ts +8 -0
  46. package/src/guard.ts +31 -0
  47. package/src/index.ts +6 -0
  48. package/src/service.ts +147 -0
  49. package/src/types.ts +32 -0
  50. package/tsconfig.json +16 -0
  51. package/tsconfig.tsbuildinfo +1 -0
package/src/service.ts ADDED
@@ -0,0 +1,147 @@
1
+ import type { Config, Context, OidcAuthService, OidcInteraction } from './types.js'
2
+ import type { FlowService } from '@owlmeans/client-flow'
3
+
4
+ import { assertContext, createService, HOME } from '@owlmeans/context'
5
+ import { DEFAULT_ALIAS } from './consts.js'
6
+ import { UserManager } from 'oidc-client-ts'
7
+ import { DEFAULT_ALIAS as FLOW_SERVICE } from '@owlmeans/client-flow'
8
+ import { FlowStepMissconfigured, OidcAuthStep, STD_OIDC_FLOW, UnknownFlow } from '@owlmeans/flow'
9
+ import type { Module } from '@owlmeans/web-client'
10
+ import { DISPATCHER_OIDC, DISPATCHER_OIDC_INIT, OIDC_CODE_QUERY } from '@owlmeans/oidc'
11
+ import type { Auth, AuthToken } from '@owlmeans/auth'
12
+ import { AUTH_RESOURCE, USER_ID } from '@owlmeans/client-auth'
13
+ import type { ClientAuthResource } from '@owlmeans/client-auth'
14
+ import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope'
15
+
16
+ export const makeOidcAuthService = (alias: string = DEFAULT_ALIAS): OidcAuthService => {
17
+ const store = (context: Context) => context.auth().store<OidcInteraction>()
18
+ const storeKey = '_oidc-client-interaction'
19
+
20
+ const service: OidcAuthService = createService<OidcAuthService>(alias, {
21
+ /**
22
+ * This method performs when the IdP returns authentication params.
23
+ */
24
+ dispatch: async params => {
25
+ /**
26
+ * 1. Check if there are parameters in the URL for the server side OIDC authentication (e.g. code)
27
+ * 2. Send paramters to finalize authentication (proxy request to the auth server?)
28
+ * 3. If the authentication successful set user state using authentication service
29
+ */
30
+ if (params[OIDC_CODE_QUERY] == null) {
31
+ return false
32
+ }
33
+
34
+ const ctx = service.assertCtx<Config, Context>()
35
+
36
+ params.authUrl = (await store(ctx).get(storeKey)).authUrl
37
+
38
+ const [authToken] = await ctx.module<Module<AuthToken>>(DISPATCHER_OIDC)
39
+ .call({ body: params })
40
+
41
+ if (authToken.token != null && authToken.token !== '') {
42
+ const authResource = ctx.resource<ClientAuthResource>(AUTH_RESOURCE)
43
+ await authResource.save({ id: USER_ID, token: authToken.token })
44
+
45
+ const [, authorization] = authToken.token.split(' ')
46
+ const envelope = makeEnvelopeModel<Auth>(authorization, EnvelopeKind.Token)
47
+
48
+ ctx.auth().auth = envelope.message()
49
+ ctx.auth().token = authToken.token
50
+
51
+ return true
52
+ }
53
+
54
+ return false
55
+ },
56
+
57
+ authenticate: async (flow, params) => {
58
+ /**
59
+ * 1. Kick of OIDC authentication if we receive some hints about who or for what organization we'd like to authenticate
60
+ * 2. Request OIDC authentication params from the server using these entity and profile id
61
+ * 3. The server should return an URL to redirect user to
62
+ * 4. Return this user to the component for the further processing (redirection)
63
+ */
64
+ if (flow.state().flow !== STD_OIDC_FLOW || flow.state().step !== OidcAuthStep.Ephemeral) {
65
+ return null
66
+ }
67
+ if (params.entity == null && params.entity == null) {
68
+ return null
69
+ }
70
+
71
+ const ctx = service.assertCtx<Config, Context>()
72
+
73
+ const [redirectTo] = await ctx.module<Module<string>>(DISPATCHER_OIDC_INIT)
74
+ .call({ body: params })
75
+
76
+ const context = service.assertCtx<Config, Context>()
77
+ await store(context).save({ id: storeKey, authUrl: redirectTo })
78
+
79
+ return redirectTo
80
+ },
81
+
82
+ proceedToRedirectUrl: async extras => {
83
+ const context = assertContext<Config, Context>(service.ctx as Context)
84
+
85
+ const flow = context.service<FlowService>(FLOW_SERVICE)
86
+ const flowModel = await flow.state()
87
+ if (flowModel == null) {
88
+ throw new UnknownFlow('oidc.dispatch')
89
+ }
90
+
91
+ const authorityTransition = flowModel.next()
92
+ flowModel.transit(authorityTransition.transition, true, { purpose: extras.purpose })
93
+
94
+ // @TODO I'm not sure that this dirty hack is a correct approach
95
+ if (extras.alias === HOME) {
96
+ const redirectTransition = flowModel.next()
97
+ flowModel.transit(redirectTransition.transition, true, { purpose: extras.purpose })
98
+ }
99
+
100
+ const redirectUrl = await flow.proceed({ params: { uid: extras.uid } }, true)
101
+
102
+ return redirectUrl
103
+ },
104
+
105
+ /**
106
+ * This is client-side only OIDC implementation. It's under constructuion.
107
+ * We stoped on the try to redirect to OIDC provider, but it requires browser integrated
108
+ * cryptography under ssl/tls.
109
+ * @TODO Finish client-side only implementation one day
110
+ */
111
+ dispatchClientOnly: async () => {
112
+ const context = assertContext<Config, Context>(service.ctx as Context)
113
+
114
+ const flow = context.service<FlowService>(FLOW_SERVICE)
115
+
116
+ const flowModel = await flow.state()
117
+ if (flowModel == null) {
118
+ throw new UnknownFlow('oidc.dispatch')
119
+ }
120
+
121
+ const authorityTransition = flowModel.next()
122
+ flowModel.transit(authorityTransition.transition, true)
123
+ const authorityStep = flowModel.step()
124
+ if (authorityStep.module == null) {
125
+ throw new FlowStepMissconfigured(authorityStep.step)
126
+ }
127
+ const [authorityUrl] = await context.module<Module>(authorityStep.module).call<string>()
128
+
129
+ const redirectTransition = flowModel.next()
130
+ flowModel.transit(redirectTransition.transition, true)
131
+
132
+ const redirectUrl = await flow.proceed(undefined, true)
133
+
134
+ // @TODO To proceed we need to provide client_id some way
135
+ const manager = new UserManager({
136
+ // client_id: context.cfg.oidc.consumer?.clientId ?? '',
137
+ client_id: '',
138
+ redirect_uri: redirectUrl,
139
+ authority: authorityUrl,
140
+ })
141
+
142
+ await manager.signinRedirect({ state: flowModel.serialize() })
143
+ }
144
+ })
145
+
146
+ return service
147
+ }
package/src/types.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { InitializedService } from '@owlmeans/context'
2
+ import type { AppConfig, AppContext } from '@owlmeans/web-client'
3
+ import type { OIDCAuthInitParams, WithSharedConfig } from '@owlmeans/oidc'
4
+ import type { OidcAuthPurposes } from './consts.js'
5
+ import type { FlowModel, FlowPayload } from '@owlmeans/flow'
6
+ import type { ResourceRecord } from '@owlmeans/resource'
7
+
8
+ export interface OidcAuthService extends InitializedService {
9
+ dispatch: (params: Record<string, string>) => Promise<boolean>
10
+
11
+ authenticate: (flow: FlowModel, params: OIDCAuthInitParams) => Promise<string | null>
12
+
13
+ // This is dedicated authentication service implementation
14
+ proceedToRedirectUrl: (extras: OidcAuthRedirectExtras) => Promise<string>
15
+
16
+ // @TODO Unfinished implementation
17
+ dispatchClientOnly: () => Promise<void>
18
+ }
19
+
20
+ export interface OidcAuthRedirectExtras extends FlowPayload {
21
+ purpose: OidcAuthPurposes
22
+ uid?: string
23
+ alias?: string
24
+ }
25
+
26
+ export interface Config extends AppConfig, WithSharedConfig { }
27
+
28
+ export interface Context<C extends Config = Config> extends AppContext<C> { }
29
+
30
+ export interface OidcInteraction extends ResourceRecord {
31
+ authUrl: string
32
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": [
3
+ "../tsconfig.default.json",
4
+ "../tsconfig.react.json",
5
+ ],
6
+ "compilerOptions": {
7
+ "rootDir": "./src/", /* Specify the root folder within your source files. */
8
+ "outDir": "./build/", /* Specify an output folder for all emitted files. */
9
+ "moduleResolution": "Bundler",
10
+ },
11
+ "exclude": [
12
+ "./dist/**/*",
13
+ "./build/**/*",
14
+ "./*.ts"
15
+ ]
16
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/consts.ts","./src/guard.ts","./src/index.ts","./src/service.ts","./src/types.ts","./src/auth/plugins/index.ts","./src/auth/plugins/oidc-client.tsx","./src/components/dispatcher.tsx","./src/components/index.ts"],"version":"5.6.3"}