AD login OK

This commit is contained in:
Douglas Barone 2023-10-18 16:04:28 -04:00
parent 7c3a309b46
commit 1d46b1cf79
8 changed files with 200 additions and 19 deletions

109
package-lock.json generated
View File

@ -16,6 +16,7 @@
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"ldapts": "^7.0.5",
"roboto-fontface": "*",
"vue": "^3.2.0",
"vue-router": "^4.0.0",
@ -557,6 +558,14 @@
"https://trpc.io/sponsor"
]
},
"node_modules/@types/asn1": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.2.tgz",
"integrity": "sha512-bqqktGboBnvFX4FzmkHzxoVgFiPJu5xnJHTK3rnksvhR+jk70pmQCxz4FLqLX6DAPXHVY/eY5ZnoJ552p6JORA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.3",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz",
@ -648,6 +657,11 @@
"@types/node": "*"
}
},
"node_modules/@types/uuid": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz",
"integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ=="
},
"node_modules/@types/webfontloader": {
"version": "1.6.35",
"resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.35.tgz",
@ -890,6 +904,14 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1149,7 +1171,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"devOptional": true,
"dependencies": {
"ms": "2.1.2"
},
@ -1646,6 +1667,23 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/ldapts": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.0.5.tgz",
"integrity": "sha512-TIHmcI4GLJY3ZQYNHYS+YMOHoDcXuYi3/gNhXT894hpx4ekQegu8sgBfm2yrmgS3d6K1BHzCOmN3ik/Qqj65dA==",
"dependencies": {
"@types/asn1": ">=0.2.1",
"@types/node": ">=18",
"@types/uuid": ">=9",
"asn1": "~0.2.6",
"debug": "~4.3.4",
"strict-event-emitter-types": "~2.0.0",
"uuid": "~9.0.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -1780,8 +1818,7 @@
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"devOptional": true
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/muggle-string": {
"version": "0.3.1",
@ -2286,6 +2323,11 @@
"node": ">= 0.8"
}
},
"node_modules/strict-event-emitter-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz",
"integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA=="
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@ -2455,6 +2497,18 @@
"node": ">= 0.4.0"
}
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -3006,6 +3060,14 @@
"resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.38.5.tgz",
"integrity": "sha512-J0d2Y3Gpt2bMohOshPBfuzDqVrPaE3OKEDtJYgTmLk5t1pZy3kXHQep4rP2LEIr+ELbmkelhcrSvvFLA+4/w/Q=="
},
"@types/asn1": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.2.tgz",
"integrity": "sha512-bqqktGboBnvFX4FzmkHzxoVgFiPJu5xnJHTK3rnksvhR+jk70pmQCxz4FLqLX6DAPXHVY/eY5ZnoJ552p6JORA==",
"requires": {
"@types/node": "*"
}
},
"@types/body-parser": {
"version": "1.19.3",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz",
@ -3097,6 +3159,11 @@
"@types/node": "*"
}
},
"@types/uuid": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz",
"integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ=="
},
"@types/webfontloader": {
"version": "1.6.35",
"resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.35.tgz",
@ -3306,6 +3373,14 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -3512,7 +3587,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"devOptional": true,
"requires": {
"ms": "2.1.2"
}
@ -3882,6 +3956,20 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
"ldapts": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.0.5.tgz",
"integrity": "sha512-TIHmcI4GLJY3ZQYNHYS+YMOHoDcXuYi3/gNhXT894hpx4ekQegu8sgBfm2yrmgS3d6K1BHzCOmN3ik/Qqj65dA==",
"requires": {
"@types/asn1": ">=0.2.1",
"@types/node": ">=18",
"@types/uuid": ">=9",
"asn1": "~0.2.6",
"debug": "~4.3.4",
"strict-event-emitter-types": "~2.0.0",
"uuid": "~9.0.1"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -3974,8 +4062,7 @@
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"devOptional": true
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"muggle-string": {
"version": "0.3.1",
@ -4325,6 +4412,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
},
"strict-event-emitter-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz",
"integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA=="
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@ -4440,6 +4532,11 @@
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
},
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

View File

@ -5,7 +5,7 @@
"clean": "rimraf ./dist",
"dev:web": "vite --host",
"dev:server": "tsx --watch ./src/server/index.ts",
"dev": "concurrently --kill-others -n Server,Web -c bgGreen,bgBlue \"npm run dev:server\" \"npm run dev:web\"",
"dev": "NODE_ENV=development concurrently --kill-others -n Server,Web -c bgGreen,bgBlue \"npm run dev:server\" \"npm run dev:web\"",
"build:web": "vue-tsc --noEmit && vite build",
"build:server": "tsc --project tsconfig.server.json",
"build": "npm run clean && npm run build:web && npm run build:server",
@ -22,6 +22,7 @@
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"ldapts": "^7.0.5",
"roboto-fontface": "*",
"vue": "^3.2.0",
"vue-router": "^4.0.0",

View File

@ -0,0 +1,32 @@
import { Client } from 'ldapts'
export class LdapLogin implements Login {
constructor(
private client: Client,
private domain: string,
private searchDN: string
) {}
async login(username: string, password: string): Promise<LoginResult> {
try {
await this.client.bind(`${this.domain}\\${username}`, password)
const search = await this.client.search(this.searchDN, {
scope: 'sub',
filter: `(sAMAccountName=${username})`,
attributes: ['displayName']
})
return {
username,
displayName: search.searchEntries[0].displayName as string
}
} catch (error: any) {
console.log('Error:', error)
throw new Error(`Login failed: ${error.message}`)
} finally {
await this.client.unbind()
}
}
}

View File

@ -0,0 +1,9 @@
type LoginResult = {
username: string
displayName: string
jwt?: string
}
interface Login {
login(username: string, password: string): Promise<LoginResult>
}

View File

@ -1,4 +1,17 @@
export function login(username: string, password: string) {
console.log('Login', username, password)
return 'ok'
import { Client } from 'ldapts'
import { LdapLogin } from '../classes/LdapLogin'
export async function login(username: string, password: string) {
const ldapClient = new Client({
url: 'ldap://10.7.0.18'
})
const ldapLogin = new LdapLogin(ldapClient, 'ifms', 'DC=ifms,DC=edu,DC=br')
const result = await ldapLogin.login(username, password)
console.log('Login result:', result)
return result
}

View File

@ -18,12 +18,14 @@ export const appRouter = t.router({
const ip = ctx.ip.split(':').slice(-1)[0]
console.log(`IP: ${ip}`)
if (process.env.NODE_ENV === 'development') return '10.7.16.254'
return ip
}),
login: t.procedure
.input(z.object({ username: z.string(), password: z.string() }))
.mutation(async ({ input }) => {
return login(input.username, input.password)
return await login(input.username, input.password)
})
})

View File

@ -1,7 +1,19 @@
<template>
<v-form @submit.prevent="doLogin">
<v-card class="pa-2" title="Fazer login na rede">
<v-card
class="pa-2"
title="Fazer login na rede"
:loading="loading"
:disabled="loading"
:style="{ width: '480px' }"
>
<v-card-text class="mt-3">
<v-scale-transition>
<v-alert class="mb-5" type="error" v-if="error">
Não foi possível fazer login. Tente novamente. Se o problema
persistir, entre em contato com o SERTI do campus.
</v-alert>
</v-scale-transition>
<v-text-field
class="mb-3"
v-model="username"
@ -9,7 +21,7 @@
:variant="'outlined'"
autocomplete="username"
hint="SIAPE ou CPF"
prepend-icon="mdi-account"
prepend-inner-icon="mdi-account"
required
/>
<v-text-field
@ -19,7 +31,7 @@
hint="Sua senha"
:variant="'outlined'"
autocomplete="current-password"
prepend-icon="mdi-key"
prepend-inner-icon="mdi-key"
:append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append-inner="showPassword = !showPassword"
required
@ -42,7 +54,7 @@
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { ref } from 'vue'
import { trpc } from '../trpc'
const username = ref('')
@ -51,7 +63,24 @@ const password = ref('')
const autoLogin = ref(false)
const showPassword = ref(false)
function doLogin() {
trpc.login.mutate({ username: username.value, password: password.value })
const loading = ref(false)
const error = ref(false)
async function doLogin() {
try {
loading.value = true
error.value = false
await trpc.login.mutate({
username: username.value,
password: password.value
})
} catch (e: any) {
console.log(e.message)
error.value = true
} finally {
loading.value = false
}
}
</script>

View File

@ -3,8 +3,6 @@ import type { AppRouter } from '../server/trpc'
const SERVER_URL = import.meta.env.VITE_SERVER_URL || ''
console.log('SERVER_URL', SERVER_URL)
// Pass AppRouter as generic here. 👇 This lets the `trpc` object know
// what procedures are available on the server and their input/output types.
export const trpc = createTRPCProxyClient<AppRouter>({