oidc-spa 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 GitHub user u/garronej
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ <p align="center">
2
+ <img src="https://user-images.githubusercontent.com/6702424/80216211-00ef5280-863e-11ea-81de-59f3a3d4b8e4.png">
3
+ </p>
4
+ <p align="center">
5
+ <i>Openidconnect client for Single Page Applications</i>
6
+ <br>
7
+ <br>
8
+ <a href="https://github.com/garronej/oidc-spa/actions">
9
+ <img src="https://github.com/garronej/oidc-spa/workflows/ci/badge.svg?branch=main">
10
+ </a>
11
+ <a href="https://bundlephobia.com/package/oidc-spa">
12
+ <img src="https://img.shields.io/bundlephobia/minzip/oidc-spa">
13
+ </a>
14
+ <a href="https://www.npmjs.com/package/oidc-spa">
15
+ <img src="https://img.shields.io/npm/dw/oidc-spa">
16
+ </a>
17
+ <a href="https://github.com/garronej/oidc-spa/blob/main/LICENSE">
18
+ <img src="https://img.shields.io/npm/l/oidc-spa">
19
+ </a>
20
+ </p>
21
+ <p align="center">
22
+ <a href="https://github.com/garronej/oidc-spa">Home</a>
23
+ -
24
+ <a href="https://github.com/garronej/oidc-spa">Documentation</a>
25
+ </p>
26
+
27
+ An OIDC client for Single Page Applications that comes with an optional adapter for React.
28
+ Very minimal API surface, you don't need to know the in and out of oidc or OAuth to use this.
29
+
30
+ Why not oidc-client-ts ?
31
+
32
+ - `oidc-client-ts` more a toolkit than a ready to use adapter. This lib use it internally but abstract away most of it's complexity.
33
+ - It's used under the hood by this lib but it's hard to setup directly in a SPA setup especially the silent SSO.
34
+ - It's more resilient do misconfigured server.
35
+ - It restrict what params can be passed on the url when redirecting to the login page.
36
+
37
+ Why not react-oidc-context?
38
+
39
+ - There's no overlap between OIDC and React. Not everything should be though as a React problem. Oidc and React are
40
+ completely different problem space they have no business being intertwined.
41
+ This library provide an optional React adapter for convenience in the spirit of being truly ready to use but don't
42
+ get mistaken, it's trivial you could as well do without it.
43
+
44
+ # Install / Import
45
+
46
+ ```bash
47
+ $ yarn add oidc-spa
48
+ ```
49
+
50
+ Create a `silent-sso.html` file and put it in your public directory.
51
+
52
+ ```html
53
+ <html>
54
+ <body>
55
+ <script>
56
+ parent.postMessage(location.href, location.origin);
57
+ </script>
58
+ </body>
59
+ </html>
60
+ ```
61
+
62
+ # Usage
63
+
64
+ ## Isolated from the UI library
65
+
66
+ ```ts
67
+ import { createOidc, decodeJwt } from "oidc-spa";
68
+
69
+ (async () => {
70
+ const oidc = await createOidc({
71
+ issuerUri: "https://auth.your-domain.net/auth/realms/myrealm",
72
+ clientId: "myclient",
73
+ // Optional, you can modify the url before redirection to the identity server
74
+ transformUrlBeforeRedirect: url => `${url}&ui_locales=fr`
75
+ /** Optional: Provide only if your app is not hosted at the origin */
76
+ //silentSsoUrl: `${window.location.origin}/foo/bar/baz/silent-sso.html`,
77
+ });
78
+
79
+ if (oidc.isUserLoggedIn) {
80
+ // This return a promise that never resolve. Your user will be redirected to the identity server.
81
+ // If you are calling login because the user clicked
82
+ // on a 'login' button you should set doesCurrentHrefRequiresAuth to false.
83
+ // When you are calling login because your user navigated to a path that require authentication
84
+ // you should set doesCurrentHrefRequiresAuth to true
85
+ oidc.login({ doesCurrentHrefRequiresAuth: false });
86
+ } else {
87
+ const {
88
+ // The accessToken is what you'll use a a Bearer token to authenticate to your APIs
89
+ accessToken,
90
+ // You can parse the idToken as a JWT to get some information about the user.
91
+ idToken
92
+ } = oidc.getTokens();
93
+
94
+ const { sub, preferred_username } = decodeJwt<{
95
+ // Use https://jwt.io/ to tell what's in your idToken
96
+ sub: string;
97
+ preferred_username: string;
98
+ }>(idToken);
99
+
100
+ // To call when the user click on logout.
101
+ oidc.logout();
102
+ }
103
+ })();
104
+ ```
105
+
106
+ ## Use via React Adapter
107
+
108
+ ```tsx
109
+ import { createOidcProvider, useOidc } from "oidc-spa/react";
110
+ import { decodeJwt } from "oidc-spa";
111
+
112
+ const { OidcProvider } = createOidcProvider({
113
+ issuerUri: "https://auth.your-domain.net/auth/realms/myrealm",
114
+ clientId: "myclient"
115
+ // See above for other parameters
116
+ });
117
+
118
+ ReactDOM.render(
119
+ <OidcProvider
120
+ // Optional, it's usually so fast that a fallback is really not required.
121
+ fallback={<>Logging you in...</>}
122
+ >
123
+ <App />
124
+ </OidcProvider>,
125
+ document.getElementById("root")
126
+ );
127
+
128
+ function App() {
129
+ const { oidc } = useOidc();
130
+
131
+ if (!oidc.isUserLoggedIn) {
132
+ return (
133
+ <>
134
+ You're not logged in.
135
+ <button onClick={() => oidc.login({ doesCurrentHrefRequiresAuth: false })}>
136
+ Login now
137
+ </button>
138
+ </>
139
+ );
140
+ }
141
+
142
+ const { preferred_username } = decodeJwt<{
143
+ preferred_username: string;
144
+ }>(oidc.getTokens().idToken);
145
+
146
+ return (
147
+ <>
148
+ <h1>Hello {preferred_username}</h1>
149
+ <button onClick={() => oidc.logout()}>Log out</button>
150
+ </>
151
+ );
152
+ }
153
+ ```
154
+
155
+ # Setup example
156
+
157
+ - Basic setup: https://github.com/keycloakify/keycloakify-starter
158
+ - Fully fledged app: https://github.com/InseeFrLab/onyxia
159
+
160
+ # Contributing
161
+
162
+ ## Testing your changes in an external app
163
+
164
+ You have made some changes to the code and you want to test them
165
+ in your app before submitting a pull request?
166
+
167
+ Assuming `you/my-app` have `oidc-spa` as a dependency.
168
+
169
+ ```bash
170
+ cd ~/github
171
+ git clone https://github.com/you/my-app
172
+ cd my-app
173
+ yarn
174
+
175
+ cd ~/github
176
+ git clone https://github.com/garronej/oidc-spa
177
+ cd oidc-spa
178
+ yarn
179
+ yarn build
180
+ yarn link-in-app my-app
181
+ npx tsc -w
182
+
183
+ # Open another terminal
184
+
185
+ cd ~/github/my-app
186
+ rm -rf node_modules/.cache
187
+ yarn start # Or whatever my-app is using for starting the project
188
+ ```
189
+
190
+ You don't have to use `~/github` as reference path. Just make sure `my-app` and `oidc-spa`
191
+ are in the same directory.
192
+
193
+ > Note for the maintainer: You might run into issues if you do not list all your singleton dependencies in
194
+ > `src/link-in-app.js -> singletonDependencies`. A singleton dependency is a dependency that can
195
+ > only be present once in an App. Singleton dependencies are usually listed as peerDependencies example `react`, `@emotion/*`.
196
+
197
+ ## Releasing
198
+
199
+ For releasing a new version on GitHub and NPM you don't need to create a tag.
200
+ Just update the `package.json` version number and push.
201
+
202
+ For publishing a release candidate update your `package.json` with `1.3.4-rc.0` (`.1`, `.2`, ...).
203
+ It also work if you do it from a branch that have an open PR on main.
204
+
205
+ > Make sure your have defined the `NPM_TOKEN` repository secret or NPM publishing will fail.
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { createOidc } from "./oidc";
2
+ export type { Oidc } from "./oidc";
3
+ import decodeJwt from "jwt-decode";
4
+ export { decodeJwt };
package/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.decodeJwt = exports.createOidc = void 0;
7
+ var oidc_1 = require("./oidc");
8
+ Object.defineProperty(exports, "createOidc", { enumerable: true, get: function () { return oidc_1.createOidc; } });
9
+ var jwt_decode_1 = __importDefault(require("jwt-decode"));
10
+ exports.decodeJwt = jwt_decode_1.default;
11
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";;;;;;AAAA,+BAAoC;AAA3B,kGAAA,UAAU,OAAA;AAEnB,0DAAmC;AAC1B,oBADF,oBAAS,CACE"}
package/oidc.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ export declare type Oidc = Oidc.LoggedIn | Oidc.NotLoggedIn;
2
+ export declare namespace Oidc {
3
+ type Common = {
4
+ params: {
5
+ issuerUri: string;
6
+ clientId: string;
7
+ };
8
+ };
9
+ type NotLoggedIn = Common & {
10
+ isUserLoggedIn: false;
11
+ login: (params: {
12
+ doesCurrentHrefRequiresAuth: boolean;
13
+ }) => Promise<never>;
14
+ };
15
+ type LoggedIn = Common & {
16
+ isUserLoggedIn: true;
17
+ renewTokens(): Promise<void>;
18
+ getTokens: () => Tokens;
19
+ logout: (params: {
20
+ redirectTo: "home" | "current page";
21
+ }) => Promise<never>;
22
+ };
23
+ type Tokens = {
24
+ accessToken: string;
25
+ accessTokenExpirationTime: number;
26
+ idToken: string;
27
+ refreshToken: string;
28
+ refreshTokenExpirationTime: number;
29
+ };
30
+ }
31
+ export declare function createOidc(params: {
32
+ issuerUri: string;
33
+ clientId: string;
34
+ transformUrlBeforeRedirect?: (url: string) => string;
35
+ /** Default `${window.location.origin}/silent-sso.html` */
36
+ silentSsoUrl?: string;
37
+ }): Promise<Oidc>;