diff --git a/frontend/src/components/Auth/Auth.js b/frontend/src/components/Auth/Auth.js
index 9afdacd2afc014f6fe84e92cd137adfdfb8c128f..5c9239aa1a5d02d04041400a00ea1b1a44c864de 100644
--- a/frontend/src/components/Auth/Auth.js
+++ b/frontend/src/components/Auth/Auth.js
@@ -1,11 +1,182 @@
-import React from 'react'
+import React, { useState, useContext } from 'react';
+import { useMutation } from '@apollo/client';
+import { useHistory } from 'react-router-dom';
+import { SIGNIN, SIGNUP } from '../../queries/queries.js';
+import { AuthContext } from '../../context/auth.js';
+import { Avatar, Button, Container, Paper, Grid, Typography } from '@material-ui/core';
+import useStyles from './styles';
+import LockOutlined from '@material-ui/icons/LockOutlined';
+import Input from './Input';
+import * as EmailValidator from 'email-validator';
+
 
 const Auth = () => {
+  const classes = useStyles();
+  const history = useHistory();
+  const context = useContext(AuthContext);
+  const [showPassword, setShowPassword] = useState(false);
+  const [isSignup, setIsSignup] = useState(false);
+  const initialState = {
+    firstName: "",
+    lastName: "",
+    email: "",
+    password: "",
+    confirmPassword: ""
+  };
+  const [formData, setFormData] = useState(initialState);
+  const [signupUser, { data }] = useMutation(SIGNUP, {
+    update(proxy, result) {
+      context.signin(result.data.signup);
+      history.push("/");
+    },
+    onError(err) {
+      setErrorData({...errorData, email: { error: true, errorMessage: "Email already in use" }});
+    }
+  });
+  const [signinUser, { data: data2 }] = useMutation(SIGNIN, {
+    update(proxy, result) {
+      context.signin(result.data.signin);
+      history.push("/");
+    },
+    onError(err) {
+      setErrorData({...errorData, email: { error: true, errorMessage: "Invalid Details" }, password: { error: true, errorMessage: "Invalid Details" }});
+    }
+  });
+
+
+  const validationState = {
+    firstName: { error: false, errorMessage: ""},
+    lastName: { error: false, errorMessage: ""},
+    email: { error: false, errorMessage: ""},
+    password: { error: false, errorMessage: ""},
+    confirmPassword: { error: false, errorMessage: ""}
+  };
+  const [errorData, setErrorData] = useState(validationState);
+
+  const validate = () => {
+    let isValid = true;
+    let startingState = {
+      firstName: { error: false, errorMessage: ""},
+      lastName: { error: false, errorMessage: ""},
+      email: { error: false, errorMessage: ""},
+      password: { error: false, errorMessage: ""},
+      confirmPassword: { error: false, errorMessage: ""}
+    };
+
+    if (formData.email.trim().length === 0) {
+      startingState = { ...startingState, email: { error: true, errorMessage: "Required" } };
+      isValid = false;
+    }
+
+    if (!EmailValidator.validate(formData.email)) {
+      startingState = { ...startingState, email: { error: true, errorMessage: "Invalid email" } };
+      isValid = false;
+    }
+
+    if (formData.password.trim().length === 0) {
+      startingState = { ...startingState, password: { error: true, errorMessage: "Required" } };
+      isValid = false;
+    }
+
+    if (isSignup) {
+      if (formData.password.trim().length < 8) {
+        startingState = { ...startingState, password: { error: true, errorMessage: "Password should be at least 8 characters" } };
+        isValid = false;
+      }
+  
+      if (formData.confirmPassword.trim().length === 0) {
+        startingState = { ...startingState, confirmPassword: { error: true, errorMessage: "Required" } };
+        isValid = false;
+      }
+  
+      if (formData.password !== formData.confirmPassword) {
+        startingState = { ...startingState, confirmPassword: { error: true, errorMessage: "Passwords must match" } };
+        isValid = false;
+      }
+  
+      if (formData.firstName.trim().length === 0) {
+        startingState = { ...startingState, firstName: { error: true, errorMessage: "Required" } };
+        isValid = false;
+      }
+  
+      if (formData.lastName.trim().length === 0) {
+        startingState = { ...startingState, lastName: { error: true, errorMessage: "Required" } };
+        isValid = false;
+      }
+    }
+
+    setErrorData(startingState);
+    return isValid;
+  };
+
+  const handleSubmit = (e) => {
+    e.preventDefault();
+
+    if (validate()) {
+      if (isSignup) {
+        signupUser({ variables: {
+            name: formData.firstName + " " + formData.lastName,
+            email: formData.email,
+            password: formData.password
+        }});
+      } else {
+        signinUser({ variables: {
+          email: formData.email,
+          password: formData.password
+        }});
+      }
+    }
+  };
+
+  const handleChange = (e) => {
+    setFormData({ ...formData, [e.target.name]: e.target.value })
+  }
+
+  const handleShowPassword = () => {
+    setShowPassword((prevState) => !prevState);
+  }
+
+  const switchMode = () => {
+    setIsSignup((prevState) => !prevState);
+    setShowPassword(false);
+    setErrorData(validationState);
+  }
+
   return (
-    <div>
-      TODO
-    </div>
+    <Container component="main" maxWidth="xs">
+      <Paper className={classes.paper} elevation={3}>
+        <Avatar className={classes.avatar}>
+          <LockOutlined  />
+        </Avatar>
+        <Typography variant="h5">{isSignup ? "Sign Up" : "Sign In"}</Typography>
+        <form className={classes.form} onSubmit={handleSubmit}>
+          <Grid container spacing={2}>
+            {
+              isSignup && (
+                <>
+                  <Input name="firstName" label="First Name" errors={errorData.firstName} handleChange={handleChange} autoFocus half/>
+                  <Input name="lastName" label="Last Name" errors={errorData.lastName} handleChange={handleChange} half/>
+                </>
+              )
+            }
+            <Input name="email" label="Email Address" errors={errorData.email} handleChange={handleChange} type="email" />
+            <Input name="password" label="Password" errors={errorData.password} handleChange={handleChange} handleShowPassword={handleShowPassword} type={showPassword ? "text" : "password"}/>
+            { isSignup && <Input name="confirmPassword" label="Confirm Password" errors={errorData.confirmPassword} handleChange={handleChange} type="password"/>}
+          </Grid>
+          <Button type="submit" fullWidth variant="contained" color="primary" className={classes.submit} onClick={validate}>
+            { isSignup ? "Sign Up" : "Sign In" }
+          </Button>
+          <Grid container justify="flex-end">
+            <Grid item>
+              <Button onClick={switchMode}>
+                { isSignup ? "Already have an account? Sign in" : "Dont have an account? Register"}
+              </Button>
+            </Grid>
+          </Grid>
+        </form>
+      </Paper>
+    </Container>
   )
 }
 
-export default Auth
+export default Auth;
diff --git a/frontend/src/components/Auth/Input.js b/frontend/src/components/Auth/Input.js
new file mode 100644
index 0000000000000000000000000000000000000000..edb1dbf7e79c3bc5ae1225b05970b838b8f6d798
--- /dev/null
+++ b/frontend/src/components/Auth/Input.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { TextField, Grid, InputAdornment, IconButton } from '@material-ui/core'
+import Visibility from '@material-ui/icons/Visibility';
+import VisibilityOff from '@material-ui/icons/VisibilityOff';
+
+const Input = ({ half, name, label, errors, autoFocus, type, handleChange, handleShowPassword }) => {
+  return (
+    <Grid item xs={12} sm={half ? 6 : 12}>
+      <TextField 
+        name={name}
+        onChange={handleChange}
+        variant="outlined"
+        required
+        fullWidth
+        error={errors.error}
+        helperText={errors.errorMessage}
+        label={label}
+        autoFocus={autoFocus}
+        type={type}
+        InputProps={name === 'password' ? {
+          endAdornment: (
+            <InputAdornment position="end">
+              <IconButton onClick={handleShowPassword}>
+                {type === 'password' ? <Visibility/> : <VisibilityOff/>}
+              </IconButton>
+            </InputAdornment>
+          )
+        } : null}
+      />
+    </Grid>
+  )
+}
+
+export default Input
diff --git a/frontend/src/components/Auth/styles.js b/frontend/src/components/Auth/styles.js
new file mode 100644
index 0000000000000000000000000000000000000000..22793f2ebeb12efcf3421e5d1b58ec721a8cae05
--- /dev/null
+++ b/frontend/src/components/Auth/styles.js
@@ -0,0 +1,31 @@
+import { makeStyles } from '@material-ui/core/styles';
+
+export default makeStyles((theme) => ({
+  paper: {
+    marginTop: theme.spacing(8),
+    marginBottom: theme.spacing(8),
+    display: 'flex',
+    flexDirection: 'column',
+    alignItems: 'center',
+    padding: theme.spacing(2),
+  },
+  root: {
+    '& .MuiTextField-root': {
+      margin: theme.spacing(1),
+    },
+  },
+  avatar: {
+    margin: theme.spacing(1),
+    backgroundColor: theme.palette.primary.main,
+  },
+  form: {
+    width: '100%',
+    marginTop: theme.spacing(3),
+  },
+  submit: {
+    margin: theme.spacing(3, 0, 2),
+  },
+  googleButton: {
+    marginBottom: theme.spacing(2),
+  },
+}));
\ No newline at end of file