@simitgroup/simpleapp-generator 2.0.2-s-alpha → 2.0.2-u-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ReleaseNote.md CHANGED
@@ -1,3 +1,13 @@
1
+ [2.0.2u-alpha]
2
+
3
+ 1. Enforced strict Keycloak token validation on backend (via AuthGuard + UserContext), returning clear 401 for invalid/expired tokens
4
+ 2. Blocked user creation when required JWT claims are missing (e.g. uid, email)
5
+ 3. Improved frontend session handling: refresh-token failures and consistently redirect to login on 401
6
+
7
+ [2.0.2t-alpha]
8
+
9
+ 1. Fix define type on service file
10
+
1
11
  [2.0.2s-alpha]
2
12
 
3
13
  1. Reduce expired-token issues
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "2.0.2s-alpha",
3
+ "version": "2.0.2u-alpha",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -93,7 +93,7 @@ export class <%= it.typename %>Service extends SimpleAppService<schema.<%= it.ty
93
93
  // <%~ JSON.stringify(fml) %>
94
94
  //const tmp = jsonpath.query(vdata,fieldpath).filter((item:string)=>item!='')
95
95
  jsonpath.apply($data, '<%~ fml.jsonPath %>', function ($item: schema.<%= fml?.paramType || it.typename %>) {
96
- return (<%~ fml.formula %>) as schema.<%= fml?.paramType || it.typename %>;
96
+ return <%~ fml.formula %>
97
97
  })
98
98
  <%}) %>
99
99
  <%} %>
@@ -6,22 +6,26 @@
6
6
  */
7
7
  import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
8
8
  import { Reflector } from '@nestjs/core';
9
- import { ResourceGuard } from 'nest-keycloak-connect';
9
+ import { AuthGuard, ResourceGuard } from 'nest-keycloak-connect';
10
+ import type { Request } from 'express';
10
11
 
11
12
  @Injectable()
12
13
  export class CustomKeycloakGuard implements CanActivate {
13
14
  constructor(
14
15
  private reflector: Reflector,
16
+ private authGuard: AuthGuard,
15
17
  private resourceGuard: ResourceGuard,
16
18
  ) {}
17
19
 
18
20
  async canActivate(context: ExecutionContext): Promise<boolean> {
19
- const request = context.switchToHttp().getRequest();
21
+ const request = context.switchToHttp().getRequest<Request>();
20
22
 
21
23
  //graphql no http request, exclude from capability of x-apikey
22
24
  if (request?.headers) {
23
- const apiKey = request.headers['x-apikey'];
24
- const apiSecret = request.headers['x-apisecret'];
25
+ const apiKeyHeader = request.headers['x-apikey'];
26
+ const apiSecretHeader = request.headers['x-apisecret'];
27
+ const apiKey = Array.isArray(apiKeyHeader) ? apiKeyHeader[0] : apiKeyHeader;
28
+ const apiSecret = Array.isArray(apiSecretHeader) ? apiSecretHeader[0] : apiSecretHeader;
25
29
  // validate apikey and apisecret at middleware level, reach here mean approved as robot
26
30
  if (apiKey && apiSecret) {
27
31
  return true;
@@ -30,8 +34,15 @@ export class CustomKeycloakGuard implements CanActivate {
30
34
 
31
35
  // If API key is not present, fall back to Keycloak authentication
32
36
  try {
33
- const canActivate = await this.resourceGuard.canActivate(context);
34
- return canActivate;
37
+ // validate and authenticate the token with keycloak
38
+ const authCanActivate = await this.authGuard.canActivate(context);
39
+ if (!authCanActivate) {
40
+ throw new UnauthorizedException('Invalid Keycloak token');
41
+ }
42
+
43
+ // then enforce resource and role based access control
44
+ const resourceCanActivate = await this.resourceGuard.canActivate(context);
45
+ return resourceCanActivate;
35
46
  } catch (error) {
36
47
  throw new UnauthorizedException('Invalid API key or Keycloak token');
37
48
  }
@@ -107,6 +107,7 @@ export default NuxtAuthHandler({
107
107
  return {
108
108
  ...token,
109
109
  accessToken: null,
110
+ refreshToken: null,
110
111
  expiresAt: 0,
111
112
  error: "RefreshAccessTokenError"
112
113
  };
@@ -126,6 +127,13 @@ export default NuxtAuthHandler({
126
127
  // console.log("session", session);
127
128
  // Send properties to the client, like an access_token from a provider.
128
129
  const sessiondata:any = {...session}
130
+
131
+ if (!token.accessToken || token['error'] === 'RefreshAccessTokenError') {
132
+ sessiondata.accessToken = null;
133
+ sessiondata.error = token['error'] ?? 'MissingAccessToken';
134
+ return sessiondata;
135
+ }
136
+
129
137
  sessiondata.accessToken = <string>token.accessToken;
130
138
  return sessiondata;
131
139
  },
@@ -135,7 +135,13 @@ export default defineEventHandler(async (event:any) => {
135
135
  }else{
136
136
 
137
137
  if (error.response?.status && error.response.status == 401) {
138
- return sendRedirect(event, '/login', 401)
138
+ // return sendRedirect(event, "/login", 401);
139
+ reject({
140
+ statusMessage: error.response.statusText,
141
+ statusCode: 401,
142
+ data: error.response.data,
143
+ });
144
+ return;
139
145
  }
140
146
  reject({
141
147
  statusMessage: error.response.statusText,