validate([ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:8|confirmed', ]); $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), ]); $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', ]); } #[OA\Post( path: "/api/login_interno", summary: "Autenticaci贸n de usuarios internos", tags: ["Auth"], requestBody: new OA\RequestBody( required: true, content: new OA\JsonContent( required: ["email", "password"], properties: [ new OA\Property(property: "email", type: "string", example: "usuario"), new OA\Property(property: "password", type: "string", example: "******") ] ) ), responses: [ new OA\Response( response: 200, description: "Login correcto", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Login correcto") ] ) ), new OA\Response( response: 401, description: "Credenciales incorrectas", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas") ] ) ) ] )] public function login_interno(Request $request) { try { $request->validate([ 'email' => 'required', 'password' => 'required' ]); $url = env('SIPA_URL') . '/' . $request->email . '/autenticar'; $response = Http::asForm()->post($url, [ 'email' => $request->email, 'password' => $request->password ]); $status = $response->status(); $body = $response->body(); // Credenciales incorrectas if ($status === 404 && str_contains($body, 'json(['message' => 'Credenciales incorrectas'], 401); } // Invalida token antiguo si existe $existingToken = Cache::get("sipa_user_token:{$request->email}"); if ($existingToken) { Cache::forget("sipa_token:{$existingToken}"); } // Generar token nuevo $token = bin2hex(random_bytes(32)); // Guardar token en cache (2h) Cache::put("sipa_token:{$token}", $request->email, 120*60); Cache::put("sipa_user_token:{$request->email}", $token, 120*60); // Respuesta SIPA $data = $response->json() ?: []; // 馃敼 SOLO ESTO SE AGREGA (formato est谩ndar Bearer) $data['access_token'] = $token; $data['token_type'] = 'Bearer'; $data['expires_in'] = 120*60; return response()->json($data, $status); } catch (\Throwable $e) { return response()->json([ 'message' => 'Error interno', 'error_real' => $e->getMessage() ], 500); } } #[OA\Post( path: "/api/login_alumno", summary: "Autenticaci贸n de alumnos", tags: ["Auth"], requestBody: new OA\RequestBody( required: true, content: new OA\JsonContent( required: ["email", "password"], properties: [ new OA\Property(property: "email", type: "string", example: "usuario"), new OA\Property(property: "password", type: "string", example: "******") ] ) ), responses: [ new OA\Response( response: 200, description: "Login correcto", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Login correcto") ] ) ), new OA\Response( response: 401, description: "Credenciales incorrectas", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas") ] ) ) ] )] public function login_alumno(Request $request) { $request->validate([ 'email' => 'required', 'password' => 'required', ]); $user = User::where('email', $request->email)->first(); if (! $user || ! Hash::check($request->password, $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], ]); } $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', ]); } #[OA\Post( path: "/api/login_externo", summary: "Autenticaci贸n de usuarios externos", tags: ["Auth"], requestBody: new OA\RequestBody( required: true, content: new OA\JsonContent( required: ["email", "password"], properties: [ new OA\Property(property: "email", type: "string", example: "usuario"), new OA\Property(property: "password", type: "string", example: "******") ] ) ), responses: [ new OA\Response( response: 200, description: "Login correcto", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Login correcto") ] ) ), new OA\Response( response: 401, description: "Credenciales incorrectas", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas") ] ) ) ] )] public function login_externo(Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required', ]); $user = User::where('email', $request->email)->first(); if (! $user || ! Hash::check($request->password, $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], ]); } $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', ]); } #[OA\Post( path: "/api/logout-sipa", summary: "Cerrar sesi贸n e invalidar token", security: [["bearerAuth" => []]], tags: ["Auth"], responses: [ new OA\Response( response: 200, description: "Sesi贸n cerrada", content: new OA\JsonContent( properties: [ new OA\Property(property: "message", type: "string", example: "Sesi贸n cerrada correctamente") ] ) ), new OA\Response(response: 401, description: "Token inv谩lido o no enviado") ] )] public function logout_sipa(Request $request) { $header = $request->header('Authorization'); if (!$header || !str_starts_with($header, 'Bearer ')) { return response()->json(['message' => 'Token requerido'], 401); } $token = str_replace('Bearer ', '', $header); $email = Cache::get("sipa_token:{$token}"); if ($email) { Cache::forget("sipa_token:{$token}"); Cache::forget("sipa_user_token:{$email}"); } return response()->json([ 'message' => 'Sesi贸n cerrada correctamente' ]); } #[OA\Post( path: "/api/refresh-sipa", summary: "Renovar token", security: [["bearerAuth" => []]], tags: ["Auth"], responses: [ new OA\Response( response: 200, description: "Token renovado", content: new OA\JsonContent( properties: [ new OA\Property(property: "access_token", type: "string", example: "nuevo_token..."), new OA\Property(property: "token_type", type: "string", example: "Bearer"), new OA\Property(property: "expires_in", type: "integer", example: 7200) ] ) ), new OA\Response(response: 401, description: "Token inv谩lido o expirado") ] )] // 馃敼 Refresh public function refresh_sipa(Request $request) { $header = $request->header('Authorization'); if (!$header || !str_starts_with($header, 'Bearer ')) { return response()->json(['message' => 'Token requerido'], 401); } $oldToken = str_replace('Bearer ', '', $header); $email = Cache::get("sipa_token:{$oldToken}"); if (!$email) { return response()->json(['message' => 'Token inv谩lido o expirado'], 401); } Cache::forget("sipa_token:{$oldToken}"); $newToken = bin2hex(random_bytes(32)); $ttl = 120 * 60; Cache::put("sipa_token:{$newToken}", $email, $ttl); Cache::put("sipa_user_token:{$email}", $newToken, $ttl); return response()->json([ 'access_token' => $newToken, 'token_type' => 'Bearer', 'expires_in' => $ttl ]); } }