@@ -46,6 +46,12 @@ const getAuthHeadersForApiKey = ({
4646 )
4747 }
4848
49+ if ( isPublishableKey ( apiKey ) ) {
50+ throw new SeamHttpInvalidTokenError (
51+ 'A Publishable Key cannot be used as an apiKey' ,
52+ )
53+ }
54+
4955 if ( ! isSeamToken ( apiKey ) ) {
5056 throw new SeamHttpInvalidTokenError (
5157 `Unknown or invalid apiKey format, expected token to start with ${ tokenPrefix } ` ,
@@ -72,6 +78,12 @@ const getAuthHeadersForClientSessionToken = ({
7278 )
7379 }
7480
81+ if ( isPublishableKey ( clientSessionToken ) ) {
82+ throw new SeamHttpInvalidTokenError (
83+ 'A Publishable Key cannot be used as a clientSessionToken' ,
84+ )
85+ }
86+
7587 if ( ! isClientSessionToken ( clientSessionToken ) ) {
7688 throw new SeamHttpInvalidTokenError (
7789 `Unknown or invalid clientSessionToken format, expected token to start with ${ clientSessionTokenPrefix } ` ,
@@ -85,6 +97,30 @@ const getAuthHeadersForClientSessionToken = ({
8597}
8698
8799const getAuthHeadersForPublishableKey = ( publishableKey : string ) : Headers => {
100+ if ( isJwt ( publishableKey ) ) {
101+ throw new SeamHttpInvalidTokenError (
102+ 'A JWT cannot be used as a publishableKey' ,
103+ )
104+ }
105+
106+ if ( isAccessToken ( publishableKey ) ) {
107+ throw new SeamHttpInvalidTokenError (
108+ 'An Access Token cannot be used as a publishableKey' ,
109+ )
110+ }
111+
112+ if ( isClientSessionToken ( publishableKey ) ) {
113+ throw new SeamHttpInvalidTokenError (
114+ 'A Client Session Token Key cannot be used as a publishableKey' ,
115+ )
116+ }
117+
118+ if ( ! isPublishableKey ( publishableKey ) ) {
119+ throw new SeamHttpInvalidTokenError (
120+ `Unknown or invalid publishableKey format, expected token to start with ${ publishableKeyTokenPrefix } ` ,
121+ )
122+ }
123+
88124 return {
89125 'seam-publishable-key' : publishableKey ,
90126 }
@@ -98,10 +134,29 @@ export class SeamHttpInvalidTokenError extends Error {
98134 }
99135}
100136
137+ export const warnOnInsecureuserIdentifierKey = (
138+ userIdentifierKey : string ,
139+ ) : void => {
140+ if ( isEmail ( userIdentifierKey ) ) {
141+ // eslint-disable-next-line no-console
142+ console . warn (
143+ ...[
144+ 'Using an email for the userIdentifierKey is insecure and may return an error in the future!' ,
145+ 'This is insecure because an email is common knowledge or easily guessed.' ,
146+ 'Use something with sufficient entropy known only to the owner of the client session.' ,
147+ 'For help choosing a user identifier key see' ,
148+ 'https://docs.seam.co/latest/seam-components/overview/get-started-with-client-side-components#3-select-a-user-identifier-key' ,
149+ ] ,
150+ )
151+ }
152+ }
153+
101154const tokenPrefix = 'seam_'
102155
103156const clientSessionTokenPrefix = 'seam_cst'
104157
158+ const publishableKeyTokenPrefix = 'seam_pk'
159+
105160const isClientSessionToken = ( token : string ) : boolean =>
106161 token . startsWith ( clientSessionTokenPrefix )
107162
@@ -110,3 +165,10 @@ const isAccessToken = (token: string): boolean => token.startsWith('seam_at')
110165const isJwt = ( token : string ) : boolean => token . startsWith ( 'ey' )
111166
112167const isSeamToken = ( token : string ) : boolean => token . startsWith ( tokenPrefix )
168+
169+ const isPublishableKey = ( token : string ) : boolean =>
170+ token . startsWith ( publishableKeyTokenPrefix )
171+
172+ // SOURCE: https://stackoverflow.com/a/46181
173+ const isEmail = ( value : string ) : boolean =>
174+ / ^ [ ^ \s @ ] + @ [ ^ \s @ ] + \. [ ^ \s @ ] + $ / . test ( value )
0 commit comments