Closed RGunning closed 5 years ago
Thanks for the PR. This is something I've been thinking of for some time, and it's a start.
My idea is to add to the generated ApiConfiguration a method per security definition.
Suppose there's a security scheme called login
, of type basic http auth, and another called apiKey
, which sets a header. Ideally, the generated ApiConfiguration would be something like:
/**
* Global configuration
*/
@Injectable({
providedIn: 'root',
})
export class ApiConfiguration {
rootUrl: string = 'http://www.example.com';
security: {
login: BasicSecurityScheme,
apiKey: ApiKeySecurityScheme
}
constructor() {
this.security = {
login: new BasicSecurityScheme(),
apiKey: new ApiKeySecurityScheme('HeaderName')
}
}
}
export interface SecurityScheme {
apply: (req: HttpRequest<any>) => HttpRequest<any>;
clear(): void;
}
export class BasicSecurityScheme implements SecurityScheme {
private username?: string;
private password?: string;
set(username: string, password: string): void {
this.username = username;
this.password = password;
}
clear() {
this.username = undefined;
this.password = undefined;
}
apply(req: HttpRequest<any>): HttpRequest<any> {
if (this.username && this.password) {
const headers = new HttpHeaders();
headers.append('Authorization', 'Basic ' + btoa(this.username + ':' + this.password));
return req.clone({
headers: headers
});
} else {
return req;
}
}
}
export class ApiKeySecurityScheme implements SecurityScheme {
private value?: string;
constructor(public header: string) {
}
set(value: string): void {
this.value = value;
}
clear() {
this.value = undefined;
}
apply(req: HttpRequest<any>): HttpRequest<any> {
if (this.value) {
const headers = new HttpHeaders();
headers.append(this.header, this.value);
return req.clone({
headers: headers
});
} else {
return req;
}
}
}
This way, for example, once the user logs in, the component would inject the ApiConfiguration
and just call:
this.apiConfiguration.security.login.set(usr, pwd);
The setup with the api configuration looks good and is pretty much how I was planning to set it up in my custom template I'm working on.
I'll keep the scope of this PR limited to the parsing, but would happily help with your suggested setup above.
I've noticed a couple of bugs in this PR that need fixed. As the parsing I did doesn't fully implement the openApi specs currently. Looking at the schema I wasn't implementing the root security, the logical and/or, or the scoping fully.
Problem
Currently, security information in the openApi file is not being parsed by the generator. Instead the documentation just recommends using HTTP interceptors.
Solution
Added basic parsing of the security schema into operations object for use in templates. I didn't add the security to the template as this will require more thought on how best to handle and may be best left to custom templates.