akveo / akveo/nebular

Create new AuthStrategy

Aperta
#2,380 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
TypeScript
Stelle
8.1k
Fork
1.5k
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

### Issue type

**I'm submitting a ...** (check one with "x")

* [ ] bug report
* [X] feature request

### Issue description

**Current behavior:**

Now we have two kind of auth strategy: NbDummyAuthStrategy and NbPasswordAuthStrategy

**Expected behavior:**

I want to implement an Auth strategy based on SOAP, because my server talks with SOAP

**Steps to reproduce:**

I created a new Auth Strategy: class SoapAuthStrategy extends NbAuthStrategy and a new class SoapAuthStrategyOptions extends NbAuthStrategyOptions
The last code shows how i import my new strategy and pass to the NbAuthModule in my Core Module (based on ngx-admin)
The problem is that i get an error that say:
There is no Auth Strategy registered under 'email' name
What am i doing wrong?

**Related code:**

**SoapAuthStrategy **
```

@Injectable()
export class SoapAuthStrategy extends NbAuthStrategy {
protected defaultOptions: SoapAuthStrategyOptions = soapStrategyOptions;
soapClient: Client;
baseUrl = "http://localhost:8000/";
authUrl = this.baseUrl + "security.asmx?wsdl";

static setup(
options: SoapAuthStrategyOptions
): [NbAuthStrategyClass, SoapAuthStrategyOptions] {
return [SoapAuthStrategy, options];
}

constructor(
private zone: NgZone,
) {
super();
createClient(this.authUrl, (err, res) => {
if (err) {
console.error("Errore createClient Auth", err);
}
this.soapClient = res;
});
}

authenticate(data?: any): Observable {
const module = "login";
const method = this.getOption(`${module}.method`);
const url = this.getActionEndpoint(module);
const requireValidToken = false; //this.getOption(`${module}.requireValidToken`);
const authArgs = {
username: data.username,
password: data.password,
ipAddress: "123456789",
workstation: "ciaone1",
clientType: "C",
};

return Observable.create((observer) => {
(this.soapClient as any).Authentication(
authArgs,
(errr, ress: AuthenticationResponse) => {
if (errr) {
console.error(errr);
observer.complete();
return this.handleResponseError(errr, "Autenticazione");
}
console.log(ress);
const sp =
ress.AuthenticationResult.diffgram.SecurityDataSet
.SP_ACT_Autenticazione_GetToken;

const soapHeaderString =
`
` +
sp.SessionDigest +
`
` +
sp.IdPersona +
`
` +
"00000000-0000-0000-0000-000000000000" +
`
` +
"123456789" +
`
`;
const nbb = {
data: {
token: {
rawString: soapHeaderString,
obj: ress.AuthenticationResult.diffgram.SecurityDataSet,
},
},
};

// this.testOk(soapHeaderString);

return this.zone.run(() => {
observer.next(
new NbAuthResult(
true,
ress,
this.getOption(`${module}.redirect.success`),
[],
this.getOption("messages.getter")(module, ress, this.options),
this.createToken(
this.getOption("token.getter")(module, nbb, this.options),
false
)
)
);

observer.complete();
});
}
);
});
}
register(data?: any): Observable {

}

requestPassword(data?: any): Observable {

}

resetPassword(data: any = {}): Observable {

}

logout(): Observable {

}

refreshToken(data?: any): Observable {

}

protected handleResponseError(
res: any,
module: string
): Observable {

}
}

```

**Soap Strategy Options**
```
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { NbAuthTokenClass, NbAuthStrategyOptions, getDeepFromObject } from '@nebular/auth';
import { ArteToken } from '../../token/arte-token';

export interface SoapStrategyModule {
alwaysFail?: boolean;
endpoint?: string;
method?: string;
redirect?: {
success?: string | null;
failure?: string | null;
};
requireValidToken?: boolean;
defaultErrors?: string[];
defaultMessages?: string[];
}

export interface SoapStrategyReset extends SoapStrategyModule {
resetPasswordTokenKey?: string;
}

export interface SoapStrategyToken {
class?: NbAuthTokenClass,
key?: string,
getter?: Function,
}

export interface SoapStrategyMessage {
key?: string,
getter?: Function,
}

export class SoapAuthStrategyOptions extends NbAuthStrategyOptions {
baseEndpoint? = '/api/auth/';
login?: boolean | SoapStrategyModule = {
alwaysFail: false,
endpoint: 'login',
method: 'post',
requireValidToken: true,
redirect: {
success: '/',
failure: null,
},
defaultErrors: ['Username/Password combination is not correct, please try again.'],
defaultMessages: ['You have been successfully logged in.'],
};
register?: boolean | SoapStrategyModule = {
alwaysFail: false,
endpoint: 'register',
method: 'post',
requireValidToken: true,
redirect: {
success: '/',
failure: null,
},
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['You have been successfully registered.'],
};
requestPass?: boolean | SoapStrategyModule = {
endpoint: 'request-pass',
method: 'post',
redirect: {
success: '/',
failure: null,
},
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['Reset password instructions have been sent to your email.'],
};
resetPass?: boolean | SoapStrategyReset = {
endpoint: 'reset-pass',
method: 'put',
redirect: {
success: '/',
failure: null,
},
resetPasswordTokenKey: 'reset_password_token',
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['Your password has been successfully changed.'],
};
logout?: boolean | SoapStrategyReset = {
alwaysFail: false,
endpoint: 'logout',
method: 'delete',
redirect: {
success: '/',
failure: null,
},
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['You have been successfully logged out.'],
};
refreshToken?: boolean | SoapStrategyModule = {
endpoint: 'refresh-token',
method: 'post',
requireValidToken: true,
redirect: {
success: null,
failure: null,
},
defaultErrors: ['Something went wrong, please try again.'],
defaultMessages: ['Your token has been successfully refreshed.'],
};
token?: SoapStrategyToken = {
class: ArteToken,
key: 'data.token',
getter: (module: string, res: any, options: SoapAuthStrategyOptions) => getDeepFromObject(
res,
options.token.key,
),
};
errors?: SoapStrategyMessage = {
key: 'data.errors',
getter: (module: string, res: HttpErrorResponse, options: SoapAuthStrategyOptions) => getDeepFromObject(
res.error,
options.errors.key,
options[module].defaultErrors,
),
};
messages?: SoapStrategyMessage = {
key: 'data.messages',
getter: (module: string, res: HttpResponse, options: SoapAuthStrategyOptions) => getDeepFromObject(
res.body,
options.messages.key,
options[module].defaultMessages,
),
};
validation?: {
password?: {
required?: boolean;
minLength?: number | null;
maxLength?: number | null;
regexp?: string | null;
};
email?: {
required?: boolean;
regexp?: string | null;
};
fullName?: {
required?: boolean;
minLength?: number | null;
maxLength?: number | null;
regexp?: string | null;
};
};
}

export const soapStrategyOptions: SoapAuthStrategyOptions = new SoapAuthStrategyOptions();
```

**Custom Token**
```
import { NbAuthToken, NbAuthTokenNotFoundError, NbAuthEmptyTokenError } from "@nebular/auth";
import { SecurityDataSet } from '../../@core/data/security';

export class ArteToken extends NbAuthToken {
genericInfo: {
build: string;
defaultLang: string;
serverUpdatePath: string;
};

rawString: string;
obj: SecurityDataSet;

static NAME = "nb:auth:arte:token";

constructor(
protected readonly token: any,
protected readonly ownerStrategyName: string,
protected createdAt?: Date
) {
super();
//console.log("token: ", token, this.payload);
//this.payload = token.obj;
try {
this.parsePayload();
} catch (err) {
if (!(err instanceof NbAuthTokenNotFoundError)) {
// token is present but has got a problem, including illegal
throw err;
}
}
this.createdAt = this.prepareCreatedAt(createdAt);
}

protected parsePayload(): any {
//this.payload = null;
if (!this.token) {
throw new NbAuthTokenNotFoundError("Token not found.");
} else {
if (!Object.keys(this.token).length) {
throw new NbAuthEmptyTokenError(
"Cannot extract payload from an empty token."
);
}
}
this.payload = this.token;
}

protected prepareCreatedAt(date: Date) {
return date ? date : new Date();
}

/**
* Returns the token's creation date
* @returns {Date}
*/
getCreatedAt(): Date {
return this.createdAt;
}

/**
* Returns the token value
* @returns string
*/
getValue(): string {
return this.token;
}

getOwnerStrategyName(): string {
return this.ownerStrategyName;
}

/**
* Is non empty and valid
* @returns {boolean}
*/
isValid(): boolean {
return !!this.getValue();
}

/**
* Validate value and convert to string, if value is not valid return empty string
* @returns {string}
*/
toString(): string {
return !!this.token ? this.token : "";
}
}

```

**Core Module**
```
export const NB_CORE_PROVIDERS = [
...MockDataModule.forRoot().providers,
...SoapDataModule.forRoot().providers,
...DATA_SERVICES,
SoapAuthStrategy,
...NbAuthModule.forRoot({
strategies: [
SoapAuthStrategy.setup({
name: "soap",
//delay: 3000,
}),
],
forms: {
login: {
socialLinks: socialLinks,
},
register: {
socialLinks: socialLinks,
},
},
}).providers,

NbSecurityModule.forRoot({
accessControl: {
guest: {
view: "*",
},
user: {
parent: "guest",
create: "*",
edit: "*",
remove: "*",
},
},
}).providers,

{
provide: NbRoleProvider,
useClass: NbSimpleRoleProvider,
},
AnalyticsService,
LayoutService,
PlayerService,
SeoService,
StateService,
];

@NgModule({
imports: [CommonModule],
exports: [NbAuthModule],
declarations: [],
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
throwIfAlreadyLoaded(parentModule, "CoreModule");
}

static forRoot(): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [...NB_CORE_PROVIDERS],
};
}
}
```

### Other information:

**npm, node, OS, Browser**
```
Node: v12.9.0, npm: v6.10.2
OS: Windows 10
Browser: Chrome
```

**Angular, Nebular**
```
"@nebular/auth": "5.0.0",
"@nebular/eva-icons": "5.0.0",
"@nebular/security": "5.0.0",
"@nebular/theme": "5.0.0",
```

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.