signinwith 1.0.1 → 1.0.2

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 (4) hide show
  1. package/package.json +3 -2
  2. package/react.jsx +30 -40
  3. package/readme.md +10 -9
  4. package/styles.css +50 -51
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signinwith",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Simple and straightforward library for sign in / sign up with thirdparty oAuth services like Google, Meta, Apple...",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,7 +8,8 @@
8
8
  "type": "module",
9
9
  "exports": {
10
10
  ".": "./index.js",
11
- "./react": "./react.jsx"
11
+ "./react": "./react.jsx",
12
+ "./styles.css": "./styles.css"
12
13
  },
13
14
  "keywords": [
14
15
  "signinwith",
package/react.jsx CHANGED
@@ -1,34 +1,19 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
 
3
- // Subcomponent: Meta (Facebook)
4
3
  const FacebookIcon = () => (
5
- <svg width="20" height="20" viewBox="0 0 32 32" fill="none">
6
- <rect width="32" height="32" rx="16" fill="#1877F2"/>
7
- <path d="M22 16.001h-3v8h-4v-8h-2v-3h2v-2c0-2.206 1.794-4 4-4h3v3h-3c-.553 0-1 .447-1 1v2h4l-1 3z" fill="#fff"/>
8
- </svg>
4
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 666.667 666.667"><defs><clipPath clipPathUnits="userSpaceOnUse" id="a"><path d="M0 700h700V0H0Z"/></clipPath></defs><g clip-path="url(#a)" transform="matrix(1.33333 0 0 -1.33333 -133.333 800)"><path d="M600 350c0 138.071-111.929 250-250 250S100 488.071 100 350c0-117.245 80.715-215.622 189.606-242.638v166.242h-51.552V350h51.552v32.919c0 85.092 38.508 124.532 122.048 124.532 15.838 0 43.167-3.105 54.347-6.211v-69.254c-5.901.621-16.149.932-28.882.932-40.993 0-56.832-15.528-56.832-55.9V350h81.659l-14.028-76.396h-67.631V101.831C504.073 116.782 600 222.182 600 350" fill="#0866ff"/><path d="M447.918 273.604 461.947 350h-81.66v27.019c0 40.372 15.839 55.899 56.832 55.899 12.733 0 22.98-.31 28.882-.931v69.253c-11.18 3.106-38.51 6.212-54.347 6.212-83.54 0-122.048-39.441-122.048-124.533v-32.92h-51.552v-76.395h51.552V107.362A250.559 250.559 0 0 1 350 100c10.254 0 20.358.632 30.288 1.83v171.774Z" fill="#fff"/></g></svg>
9
5
  );
10
6
 
11
7
  const GoogleIcon = () => (
12
- <svg width="20" height="20" viewBox="0 0 32 32" fill="none">
13
- <g>
14
- <circle cx="16" cy="16" r="16" fill="#fff"/>
15
- <path d="M27 16.082c0-.638-.057-1.252-.163-1.837H16v3.478h6.18a5.29 5.29 0 0 1-2.293 3.47v2.885h3.7C25.98 22.13 27 19.345 27 16.082z" fill="#4285F4"/>
16
- <path d="M16 27c2.43 0 4.47-.805 5.96-2.19l-3.7-2.885c-1.03.69-2.35 1.1-3.77 1.1-2.9 0-5.36-1.96-6.24-4.6h-3.8v2.89A10.997 10.997 0 0 0 16 27z" fill="#34A853"/>
17
- <path d="M9.76 18.425A6.594 6.594 0 0 1 9.2 16c0-.84.15-1.655.41-2.425v-2.89h-3.8A10.997 10.997 0 0 0 5 16c0 1.73.41 3.37 1.17 4.825l3.59-2.4z" fill="#FBBC05"/>
18
- <path d="M16 9.6c1.32 0 2.5.455 3.43 1.35l2.57-2.57C20.47 6.81 18.43 6 16 6A10.997 10.997 0 0 0 5.81 10.685l3.8 2.89C10.64 11.56 13.1 9.6 16 9.6z" fill="#EA4335"/>
19
- </g>
20
- </svg>
8
+ <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/><path d="M1 1h22v22H1z" fill="none"/></svg>
21
9
  );
22
10
 
23
11
  const AppleIcon = () => (
24
- <svg width="20" height="20" viewBox="0 0 32 32" fill="none">
25
- <g>
26
- <circle cx="16" cy="16" r="16" fill="#000"/>
27
- <path d="M22.67 23.13c-.53 1.13-1.16 2.25-2.08 2.27-.89.02-1.18-.72-2.45-.72-1.27 0-1.6.7-2.44.74-.98.04-1.73-1.22-2.27-2.34-1.24-2.54-2.18-7.19.09-8.97.86-.67 2.09-.47 3.36-.47 1.26 0 2.46-.21 3.36.47 1.03.8 1.45 2.22 1.2 3.44-.25 1.22-1.01 1.82-1.01 1.82s1.13.18 1.99 1.13c.86.95.7 2.36.18 3.13zM18.6 8.8c.59-.7 1.01-1.68.89-2.67-.86.04-1.89.57-2.5 1.27-.55.62-1.04 1.62-.86 2.58.97.08 1.88-.49 2.47-1.18z" fill="#fff"/>
28
- </g>
29
- </svg>
12
+ <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="814" height="1000"><path fill="#FFFFFF" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
30
13
  );
31
- export function SignInWithMeta({ service, onSignin }) {
14
+
15
+ // Subcomponent: Facebook (Facebook)
16
+ export function SignInWithFacebook({ service, onSignin, onError }) {
32
17
  useEffect(() => {
33
18
  if (!window.FB) {
34
19
  window.fbAsyncInit = function () {
@@ -50,18 +35,20 @@ export function SignInWithMeta({ service, onSignin }) {
50
35
  }
51
36
  }, [service.appId]);
52
37
 
53
- const handleLogin = () => {
38
+ const handleLogin = (e) => {
39
+ e.stopPropagation();
40
+ e.preventDefault();
54
41
  window.FB.login(function (response) {
55
42
  if (response.authResponse) {
56
- onSignin('meta', { accessToken: response.authResponse.accessToken });
43
+ onSignin('facebook', { accessToken: response.authResponse.accessToken });
57
44
  }
58
45
  }, { scope: 'email,public_profile' });
59
46
  };
60
47
 
61
- return <button className="signinwith-button signinwith-button-meta" onClick={handleLogin}><FacebookIcon />Continue with Facebook</button>;
48
+ return <button className="signinwith-button signinwith-button-facebook" onClick={handleLogin}><FacebookIcon />Continue with Facebook</button>;
62
49
  }
63
50
  // Subcomponent: Google
64
- export function SignInWithGoogle({ service, onSignin }) {
51
+ export function SignInWithGoogle({ service, onSignin, onError }) {
65
52
  useEffect(() => {
66
53
  const script = document.createElement('script');
67
54
  script.src = 'https://accounts.google.com/gsi/client';
@@ -70,6 +57,7 @@ export function SignInWithGoogle({ service, onSignin }) {
70
57
  script.onload = () => {
71
58
  window.google.accounts.id.initialize({
72
59
  client_id: service.clientId,
60
+ use_fedcm_for_prompt: true,
73
61
  callback: (res) => {
74
62
  onSignin('google', { credential: res.credential });
75
63
  }
@@ -85,13 +73,11 @@ export function SignInWithGoogle({ service, onSignin }) {
85
73
  };
86
74
  }, [service.clientId]);
87
75
 
88
- const handleGoogleLogin = () => {
89
- window.google.accounts.id.requestCredential({
90
- clientId: service.clientId,
91
- callback: (res) => {
92
- onSignin('google', { credential: res.credential });
93
- },
94
- scopes: ['email', 'profile']
76
+ const handleGoogleLogin = (e) => {
77
+ e.stopPropagation();
78
+ e.preventDefault();
79
+ window.google.accounts.id.prompt((notification) => {
80
+ onError?.(notification.getDismissedReason() || 'Sign-in with Google failed.');
95
81
  });
96
82
  };
97
83
 
@@ -103,7 +89,7 @@ export function SignInWithGoogle({ service, onSignin }) {
103
89
  }
104
90
 
105
91
  // Subcomponent: Apple
106
- export function SignInWithApple({ service, onSignin }) {
92
+ export function SignInWithApple({ service, onSignin, onError }) {
107
93
  useEffect(() => {
108
94
  const script = document.createElement('script');
109
95
  script.src = 'https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js';
@@ -120,18 +106,22 @@ export function SignInWithApple({ service, onSignin }) {
120
106
  };
121
107
  document.body.appendChild(script);
122
108
  }, [service.clientId]);
123
-
124
- return <button className="signinwith-button signinwith-button-apple" onClick={() => window.AppleID.auth.signIn()}><AppleIcon />Continue with Apple</button>;
109
+ const handleAppleLogin = (e) => {
110
+ e.stopPropagation();
111
+ e.preventDefault();
112
+ window.AppleID.auth.signIn();
113
+ };
114
+ return <button className="signinwith-button signinwith-button-apple" onClick={handleAppleLogin}><AppleIcon />Continue with Apple</button>;
125
115
  }
126
116
 
127
117
  // Main SignInWith Component
128
- export default function SignInWith({ onSignin, services, theme = 'light' }) {
118
+ export default function SignInWith({ onSignin, onError, services, theme = 'light' }) {
129
119
  return (
130
- <div style={{ display: 'flex', gap: '1rem', flexDirection: 'column' }}>
120
+ <div className={`signinwith-container signinwith-theme-${theme}`}>
131
121
  {Object.entries(services).map(([key, config]) => {
132
- if (key === 'google') return <SignInWithGoogle key={key} service={config} onSignin={onSignin} />;
133
- if (key === 'meta') return <SignInWithMeta key={key} service={config} onSignin={onSignin} />;
134
- if (key === 'apple') return <SignInWithApple key={key} service={config} onSignin={onSignin} />;
122
+ if (key === 'google') return <SignInWithGoogle key={key} service={config} onSignin={onSignin} onError={onError} />;
123
+ if (key === 'facebook') return <SignInWithFacebook key={key} service={config} onSignin={onSignin} onError={onError} />;
124
+ if (key === 'apple') return <SignInWithApple key={key} service={config} onSignin={onSignin} onError={onError} />;
135
125
  return null;
136
126
  })}
137
127
  </div>
package/readme.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Sign In With
2
2
 
3
- A simple and straightforward library for adding "Sign in with..." buttons (Google, Meta/Facebook, Apple) to your web application, handling both the frontend UI (React) and backend verification.
3
+ A simple and straightforward library for adding "Sign in with..." buttons (Google, Facebook/Meta, Apple) to your web application, handling both the frontend UI (React) and backend verification.
4
4
 
5
5
  ## Features
6
6
 
7
- * Easy integration for Google, Meta (Facebook), and Apple sign-in.
7
+ * Easy integration for Google, Facebook (Meta), and Apple sign-in.
8
8
  * React components for the frontend buttons.
9
9
  * Backend utility functions to verify the identity tokens/access tokens.
10
10
  * Basic customizable styling.
@@ -65,7 +65,7 @@ function App() {
65
65
  return (
66
66
  <div className="signinwith-container">
67
67
  <h2>Sign In</h2>
68
- <SignInWith services={services} onSignin={handleSignin} />
68
+ <SignInWith services={services} onSignin={handleSignin} onError={error=>console.error(error)} />
69
69
  </div>
70
70
  );
71
71
  }
@@ -76,7 +76,8 @@ export default App;
76
76
  ### Props for `SignInWith`
77
77
 
78
78
  * `services` (Object, required): An object where keys are the service names (`google`, `meta`, `apple`) and values are their respective configuration objects.
79
- * `onSignin` (Function, required): A callback function that receives `(serviceName, data)` when a sign-in attempt is successful on the client-side. `data` contains the necessary information (e.g., `credential` for Google, `accessToken` for Meta, `authorization` object for Apple) to be sent to your backend for verification.
79
+ * `onSignin` (Function, required): A callback function that receives `(serviceName, data)` when a sign-in attempt is successful on the client-side. `data` contains the necessary information (e.g., `credential` for Google, `accessToken` for Facebook, `authorization` object for Apple) to be sent to your backend for verification.
80
+ * `onError` (Function, optional): A callback function that receives an error string if there's an issue during the sign-in process.
80
81
 
81
82
  ## Backend Verification
82
83
 
@@ -96,8 +97,8 @@ const servicesConfig = {
96
97
  google: {
97
98
  clientId: process.env.GOOGLE_CLIENT_ID,
98
99
  },
99
- meta: {
100
- // Meta verification only needs the access token from the frontend
100
+ facebook: {
101
+ // Facebook verification only needs the access token from the frontend
101
102
  // No specific backend config needed here for the library function itself
102
103
  // but you might need App ID/Secret for other Graph API calls.
103
104
  },
@@ -145,7 +146,7 @@ The main `verifySignin` function delegates to service-specific functions:
145
146
  * `verifySigninGoogle(config, verificationData)`: Verifies Google ID token.
146
147
  * `config`: Needs `{ clientId }`.
147
148
  * `verificationData`: Needs `{ credential }`.
148
- * `verifySigninMeta(config, verificationData)`: Verifies Meta access token by fetching user email.
149
+ * `verifySigninFacebook(config, verificationData)`: Verifies Facebook access token by fetching user email.
149
150
  * `config`: Not directly used by the function, but you need your App ID configured on the frontend.
150
151
  * `verificationData`: Needs `{ accessToken }`.
151
152
  * `verifySigninApple(config, verificationData)`: Verifies Apple ID token.
@@ -171,8 +172,8 @@ You can override these styles in your own CSS. The container in the example uses
171
172
  * Add your domain(s) to "Authorized JavaScript origins".
172
173
  * Add your backend callback URL (if applicable) to "Authorized redirect URIs".
173
174
  * Get your **Client ID**.
174
- * **Meta (Facebook):**
175
- * Create an App at [Meta for Developers](https://developers.facebook.com/).
175
+ * **Facebook (Meta):**
176
+ * Create an App at [Facebook for Developers](https://developers.facebook.com/).
176
177
  * Set up "Facebook Login for Business".
177
178
  * Add your domain(s) to the App Domains and Site URL in the app settings.
178
179
  * Get your **App ID**.
package/styles.css CHANGED
@@ -1,56 +1,55 @@
1
- .signinwith-button {
2
- display: inline-flex;
3
- align-items: center;
4
- justify-content: center;
5
- padding: 10px 24px;
6
- border: 1px solid #dadce0;
7
- border-radius: 4px;
8
- font-size: 14px;
9
- font-weight: 500;
10
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
11
- cursor: pointer;
12
- text-align: center;
13
- text-decoration: none;
14
- min-width: 220px;
15
- height: 40px;
16
- box-sizing: border-box;
17
- transition: background-color 0.3s ease, border-color 0.3s ease;
18
- color: #3c4043;
19
- background-color: #ffffff;
20
-
21
- &:hover {
22
- background-color: #f8f9fa;
23
- }
24
-
25
- &-meta {
26
- background-color: #1877F2;
27
- color: white;
28
- border-color: #1877F2;
29
-
30
- &:hover {
31
- background-color: #166FE5;
1
+ .signinwith-container {
2
+ display: flex;
3
+ gap: 10px;
4
+ flex-direction: column;
5
+ align-items: stretch;
6
+ padding:10px 0px;
7
+ .signinwith-button {
8
+ display: inline-flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ padding: 10px 24px;
12
+ border: 1px solid #dadce0;
13
+ border-radius: 4px;
14
+ font-size: 14px;
15
+ font-weight: 500;
16
+ cursor: pointer;
17
+ text-align: center;
18
+ text-decoration: none;
19
+ align-self: stretch;
20
+ box-sizing: border-box;
21
+ transition: background-color 0.3s ease, border-color 0.3s ease;
22
+ color: #3c4043;
23
+ background-color: #ffffff;
24
+
25
+ & svg {
26
+ width:auto;
27
+ height:20px;
28
+ margin-right: 4px;
32
29
  }
33
- }
34
-
35
- &-apple {
36
- background-color: #000000;
37
- color: white;
38
- border-color: #000000;
39
-
30
+
40
31
  &:hover {
41
- background-color: #333333;
32
+ background-color: #f8f9fa;
33
+ }
34
+
35
+ &.signinwith-button-facebook {
36
+ background-color: #1877F2;
37
+ color: white;
38
+ border-color: #0866ff;
39
+
40
+ &:hover {
41
+ background-color: #0866ff;
42
+ }
43
+ }
44
+
45
+ &.signinwith-button-apple {
46
+ background-color: #000000;
47
+ color: white;
48
+ border-color: #000000;
49
+
50
+ &:hover {
51
+ background-color: #333333;
52
+ }
42
53
  }
43
54
  }
44
- }
45
-
46
-
47
- #google-signin-btn > div {
48
- margin: 0 !important;
49
- }
50
-
51
- .signinwith-container {
52
- display: flex;
53
- gap: 1rem;
54
- flex-direction: column;
55
- align-items: center;
56
55
  }