Commit Initial

Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
Florian Bouillon 2021-05-27 18:07:13 +02:00
commit c337823c94
Signed by: Florian Bouillon
GPG Key ID: 50BD648F12C86AB6
14 changed files with 2529 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.env
node_modules
.next

6
README.md Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,6 @@
*
box-sizing border-box
html
body
margin 0

32
src/pages/index.tsx Normal file
View 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()
}
}
}

View 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
},
}
}
}

View 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
View 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"
]
}

2211
yarn.lock Normal file

File diff suppressed because it is too large Load Diff