mirror of
https://github.com/Aviortheking/CA_Cyber_Security.git
synced 2025-04-22 19:02:14 +00:00
Commit Initial
Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
commit
c337823c94
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.env
|
||||
node_modules
|
||||
.next
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# implémentation de l'OAuth2 de Google
|
||||
|
||||
Project pour Campus Academy par
|
||||
|
||||
- Florian Bouillon
|
||||
- Nicolas Brossard
|
7
next-env.d.ts
vendored
Normal file
7
next-env.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
|
||||
declare module '*.styl' {
|
||||
const content: any
|
||||
export = content
|
||||
}
|
31
next.config.js
Normal file
31
next.config.js
Normal file
@ -0,0 +1,31 @@
|
||||
const stylus = require('next-pre-css')
|
||||
const withPlugins = require('next-compose-plugins')
|
||||
const {PHASE_DEVELOPMENT_SERVER} = require('next/constants')
|
||||
|
||||
module.exports = withPlugins([
|
||||
[stylus, {
|
||||
cssModules: true,
|
||||
cssLoaderOptions: {
|
||||
localIdentName: "[hash:base64:6]",
|
||||
},
|
||||
[PHASE_DEVELOPMENT_SERVER]: {
|
||||
cssLoaderOptions: {
|
||||
localIdentName: "[path][name]__[local]"
|
||||
}
|
||||
}
|
||||
}]
|
||||
], {
|
||||
experimental: {
|
||||
modern: true
|
||||
},
|
||||
images: {
|
||||
domains: [
|
||||
'external-content.duckduckgo.com'
|
||||
]
|
||||
},
|
||||
future: {
|
||||
webpack5: true,
|
||||
strictPostcssConfiguration: true
|
||||
}
|
||||
}
|
||||
)
|
26
package.json
Normal file
26
package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "CA_Cyber_Security",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@dzeio/url-manager": "^1.0.5",
|
||||
"@types/node": "^15.6.1",
|
||||
"next": "^10.2.3",
|
||||
"next-compose-plugins": "^2.2.1",
|
||||
"next-pre-css": "^1.0.0",
|
||||
"nextjs": "^0.0.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"stylus": "^0.54.8",
|
||||
"stylus-loader": "^6.0.0",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^4.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.8"
|
||||
}
|
||||
}
|
1
public/google.svg
Normal file
1
public/google.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 75 24" width="75" height="24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="l5Lhkf"><g id="qaEJec"><path fill="#ea4335" d="M67.954 16.303c-1.33 0-2.278-.608-2.886-1.804l7.967-3.3-.27-.68c-.495-1.33-2.008-3.79-5.102-3.79-3.068 0-5.622 2.41-5.622 5.96 0 3.34 2.53 5.96 5.92 5.96 2.73 0 4.31-1.67 4.97-2.64l-2.03-1.35c-.673.98-1.6 1.64-2.93 1.64zm-.203-7.27c1.04 0 1.92.52 2.21 1.264l-5.32 2.21c-.06-2.3 1.79-3.474 3.12-3.474z"></path></g><g id="YGlOvc"><path fill="#34a853" d="M58.193.67h2.564v17.44h-2.564z"></path></g><g id="BWfIk"><path fill="#4285f4" d="M54.152 8.066h-.088c-.588-.697-1.716-1.33-3.136-1.33-2.98 0-5.71 2.614-5.71 5.98 0 3.338 2.73 5.933 5.71 5.933 1.42 0 2.548-.64 3.136-1.36h.088v.86c0 2.28-1.217 3.5-3.183 3.5-1.61 0-2.6-1.15-3-2.12l-2.28.94c.65 1.58 2.39 3.52 5.28 3.52 3.06 0 5.66-1.807 5.66-6.206V7.21h-2.48v.858zm-3.006 8.237c-1.804 0-3.318-1.513-3.318-3.588 0-2.1 1.514-3.635 3.318-3.635 1.784 0 3.183 1.534 3.183 3.635 0 2.075-1.4 3.588-3.19 3.588z"></path></g><g id="e6m3fd"><path fill="#fbbc05" d="M38.17 6.735c-3.28 0-5.953 2.506-5.953 5.96 0 3.432 2.673 5.96 5.954 5.96 3.29 0 5.96-2.528 5.96-5.96 0-3.46-2.67-5.96-5.95-5.96zm0 9.568c-1.798 0-3.348-1.487-3.348-3.61 0-2.14 1.55-3.608 3.35-3.608s3.348 1.467 3.348 3.61c0 2.116-1.55 3.608-3.35 3.608z"></path></g><g id="vbkDmc"><path fill="#ea4335" d="M25.17 6.71c-3.28 0-5.954 2.505-5.954 5.958 0 3.433 2.673 5.96 5.954 5.96 3.282 0 5.955-2.527 5.955-5.96 0-3.453-2.673-5.96-5.955-5.96zm0 9.567c-1.8 0-3.35-1.487-3.35-3.61 0-2.14 1.55-3.608 3.35-3.608s3.35 1.46 3.35 3.6c0 2.12-1.55 3.61-3.35 3.61z"></path></g><g id="idEJde"><path fill="#4285f4" d="M14.11 14.182c.722-.723 1.205-1.78 1.387-3.334H9.423V8.373h8.518c.09.452.16 1.07.16 1.664 0 1.903-.52 4.26-2.19 5.934-1.63 1.7-3.71 2.61-6.48 2.61-5.12 0-9.42-4.17-9.42-9.29C0 4.17 4.31 0 9.43 0c2.83 0 4.843 1.108 6.362 2.56L14 4.347c-1.087-1.02-2.56-1.81-4.577-1.81-3.74 0-6.662 3.01-6.662 6.75s2.93 6.75 6.67 6.75c2.43 0 3.81-.972 4.69-1.856z"></path></g></svg>
|
After Width: | Height: | Size: 2.0 KiB |
66
src/libs/GoogleClient.ts
Normal file
66
src/libs/GoogleClient.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import URLManager from '@dzeio/url-manager'
|
||||
|
||||
interface userInformations {
|
||||
family_name: string
|
||||
name: string
|
||||
picture: string
|
||||
locale: string
|
||||
email: string
|
||||
given_name: string
|
||||
id: string
|
||||
verified_email: boolean
|
||||
}
|
||||
|
||||
export default class GoogleClient {
|
||||
|
||||
public static config = {
|
||||
clientID: process.env.GOOGLE_CLIENT_ID || '',
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
|
||||
redirectURI: process.env.GOOGLE_REDIRECT || ''
|
||||
}
|
||||
|
||||
public static scopes = [
|
||||
'email',
|
||||
'https://www.googleapis.com/auth/userinfo.profile'
|
||||
]
|
||||
|
||||
|
||||
public static getUrl(): string {
|
||||
return new URLManager('https://accounts.google.com/o/oauth2/v2/auth')
|
||||
.query('client_id', this.config.clientID || '')
|
||||
.query('redirect_uri', this.config.redirectURI || '')
|
||||
.query('response_type', 'code')
|
||||
.query('scope', this.scopes.join(encodeURI(' ')))
|
||||
.toString()
|
||||
}
|
||||
|
||||
public static async processCode(code: string): Promise<{id: string, email: string}> {
|
||||
// Fetch Access Token
|
||||
const url1 = new URLManager()
|
||||
.query('code', code)
|
||||
.query('redirect_uri', encodeURI(this.config.redirectURI))
|
||||
.query('client_id', this.config.clientID)
|
||||
.query('client_secret', this.config.clientSecret)
|
||||
.query('grant_type', 'authorization_code')
|
||||
|
||||
const { access_token }: {access_token: string} = await fetch('https://oauth2.googleapis.com/token', {
|
||||
body: url1.toString().substr(1),
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}).then((resp) => resp.json())
|
||||
|
||||
// Fetch informations
|
||||
const { id, email }: userInformations = await fetch('https://www.googleapis.com/userinfo/v2/me', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${access_token}`
|
||||
}
|
||||
}).then((resp) => resp.json())
|
||||
|
||||
return {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
}
|
13
src/pages/_app.tsx
Normal file
13
src/pages/_app.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import App from 'next/app'
|
||||
import React from 'react'
|
||||
|
||||
import './general.styl'
|
||||
|
||||
export default class Application extends App {
|
||||
|
||||
public render() {
|
||||
const { Component, pageProps } = this.props
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
6
src/pages/general.styl
Normal file
6
src/pages/general.styl
Normal file
@ -0,0 +1,6 @@
|
||||
*
|
||||
box-sizing border-box
|
||||
|
||||
html
|
||||
body
|
||||
margin 0
|
32
src/pages/index.tsx
Normal file
32
src/pages/index.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { GetServerSideProps } from 'next'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import Router from 'next/router'
|
||||
import GoogleClient from '../libs/GoogleClient'
|
||||
import css from './style.module.styl'
|
||||
|
||||
interface Props {
|
||||
oauth: string
|
||||
}
|
||||
|
||||
export default class Index extends React.Component<Props> {
|
||||
public render = () => (
|
||||
<div className={css.parent}>
|
||||
<div className={css.boxWrapper}>
|
||||
<Image src="/google.svg" width={75} height={24} />
|
||||
<p className={css.title}>Connexion</p>
|
||||
<p className={css.txt}>Utiliser votre compote Google</p>
|
||||
<i className={css.sub}>S'il ne s'agit pas de votre ordinateur, blablabla, En savoir plus</i>
|
||||
<a className={css.button} href={this.props.oauth}>Google</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<Props> = async (ctx) => {
|
||||
return {
|
||||
props: {
|
||||
oauth: GoogleClient.getUrl()
|
||||
}
|
||||
}
|
||||
}
|
57
src/pages/informations.tsx
Normal file
57
src/pages/informations.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import { GetServerSideProps } from 'next'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import Router from 'next/router'
|
||||
import GoogleClient from '../libs/GoogleClient'
|
||||
import css from './style.module.styl'
|
||||
import URLManager from '@dzeio/url-manager'
|
||||
|
||||
interface Props {
|
||||
code: string
|
||||
email: string
|
||||
id: string
|
||||
}
|
||||
|
||||
export default class Index extends React.Component<Props> {
|
||||
public render = () => (
|
||||
<div className={css.parent}>
|
||||
<div className={css.boxWrapper}>
|
||||
<Image src="/google.svg" width={75} height={24} />
|
||||
<p className={css.txt}>Code: {this.props.code}</p>
|
||||
<p className={css.txt}>Email: {this.props.email}</p>
|
||||
<i className={css.txt}>Id: {this.props.id}</i>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<Props> = async (ctx) => {
|
||||
const { code } = ctx.query as { code: string }
|
||||
try {
|
||||
const infos = await GoogleClient.processCode(code)
|
||||
if (!infos.email || !infos.id) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
statusCode: 301
|
||||
},
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
code,
|
||||
email: infos.email,
|
||||
id: infos.id
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
statusCode: 301
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
40
src/pages/style.module.styl
Normal file
40
src/pages/style.module.styl
Normal file
@ -0,0 +1,40 @@
|
||||
.button
|
||||
background #1973E8
|
||||
color white
|
||||
text-decoration none
|
||||
padding 8px 16px
|
||||
border-radius 8px
|
||||
font-family sans-serif
|
||||
display inline-block
|
||||
|
||||
.boxWrapper
|
||||
margin auto
|
||||
padding 16px
|
||||
border 1px solid #DADCE0
|
||||
border-radius 16px
|
||||
display inline-block
|
||||
text-align center
|
||||
|
||||
.parent
|
||||
display flex
|
||||
align-content center
|
||||
justify-content center
|
||||
height 100vh
|
||||
|
||||
.title
|
||||
font-size 1.3rem
|
||||
font-family sans-serif
|
||||
font-weight bold
|
||||
margin-bottom 8px
|
||||
|
||||
.txt
|
||||
font-family sans-serif
|
||||
font-size 1rem
|
||||
margin 0
|
||||
|
||||
.sub
|
||||
font-family sans-serif
|
||||
font-size .8rem
|
||||
margin 8px 0
|
||||
|
||||
display block
|
30
tsconfig.json
Normal file
30
tsconfig.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"baseUrl": "./src"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user