I'm currently making some web site which need authentication.
I use Next(React) and typescript for web dev.
My goal is to make most of pages as ServerSideRendered or StaticHTML.
But I faced problem at the very beginning of development.
I'm currently making login page and overall work flow is below.
- Server renders LoginForm include RSA-public-key (for encrypting email and password)
- User writes email address and password and click 'Submit Button' in form.
- In the web browser, it will be encrypted with RSA public key then sent to server via http request.
- The server accept it then create session and tokens then send it into client. (Maybe, I guess it can be achieved by receiving token and routing to next page -- Can you correct it too?)
The problem I faced with is on 3
-- encrypt before fetch.
Since it is server side rendered and I didn't put any of react CSR code. It should be encrypted with certain ways. And I ends up with use external script using script tag --put some js files into /public/script/
then import it and run it from browser.
- /pages/auth/login.tsx
import React, { Component } from 'react';
import Head from 'next/head';
import { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import { RSAHash } from '../../types/alias'; // RSAHash euquivalent with dtype 'string' just alias
import rsa from '../../lib/server-rsa'; // Server-side RSA encryption module
interface LogInProps {
encryptKey: RSAHash
}
export default class LogIn extends Component<LogInProps> {
render() {
return (
<>
<Head>
<script type='module' src='/script/user/submitLoginForm.js' async={false}></script>
</Head>
<form>
<input id='encryptKey' type='hidden' defaultValue={this.props.encryptKey}/> {/* RSA public key */}
<label>Email Address :
<input id='email' type='email'/>
</label>
<label>Password :
<input id='password' type='password'/>
</label>
<button type='submit'>Login</button> {/* !!HERE!! */}
</form>
</>
);
}
}
export const getServerSideProps: GetServerSideProps = async (ctx: GetServerSidePropsContext): Promise<GetServerSidePropsResult<LogInProps>> => {
// Put RSA public key to props for encryption on browser
return {
props: {
encryptKey: rsa.getPublicKey(),
},
};
}
- /public/script/user/submitLoginForm.js
import OpenCrypto from "../library/opencrypto.js";
function submitLoginForm() {
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const key = document.getElementById('encryptKey').textContent;
const crypt = new OpenCrypto();
const emailCipher = crypt.rsaEncrypt(credit, email);
const passwordCipher = crypt.rsaEncrypt(credit, sha256(password));
// Also there are function sha256(_) which encrypt to sha256 hash -- not implemented yet-- it is implemented like opencrypto did
console.log(`Receive data ${email} / ${password}`);
console.log(`Got cipher`)
console.log(emailCipher);
console.log(passwordCipher);
// Send POST request for login, then receive session. then proceed with web site maybe?
}
- /public/script/library/opencrypto.js
// Some external lightweight RSA encryption library
What I want to know is how can I make browser run function submitLoginForm()
in tag.
I think I can run it by adding onSubmit="submitLoginForm()"
to submit
type input
. (Position I marked as '!!HERE!!') But it is typescript and it deny to accept string
as prop of onSubmit
.
It shows error Type 'string' is not assignable to type '((event: FormEvent<HTMLButtonElement>) => void) | undefined'.
.
First, Is this right way to run script?
Second, If so, how can I put run
command in that HTML?
Third, Ultimately, is it right approach for the feature? I try to avoid using libraries like next-auth and so on... (But I'm gonna use JWTToken for session)
Least of codes can be wrong since I'm quite new to Web Dev. Appreciate if check that too.
Thank you.
Appendix.
I tested rendered page with inspector and checked below.
- Login page renders well with
getServerSideProps
-- means RSA pub token is inserted well.
- When checking network panel, I can see external script and it's
crypto
library is received well with status 200 and I can see the code from browser.
question from:
https://stackoverflow.com/questions/65933166/how-to-process-data-before-sending-to-server-in-next-js-environment 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…