Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[typescript-angular2] Allow lazy oauth token refresh (async access_token function) #6486

Closed
alexrashed opened this issue Sep 13, 2017 · 8 comments

Comments

@alexrashed
Copy link

Description

In case of an OAuth2 implicit flow the current implementation of the Configuration class allows the accessToken to either be a string or a function returning a string (directly). In order to allow a lazy update of the (already expired) access_token using the (still valid) refresh_token the function should get the name of the authorization scheme as well as the necessary scopes and should return an Observable<string>.

export class Configuration {
    ...
    accessToken?: string | ((name: string, scopes?: string[]) => string) => Observable<string>);
    ...
}

This would allow an asynchronous implementation of the accessToken function where the auth server can be requested for a new token.

Swagger-codegen version

2.3.0-SNAPSHOT

Command line used for generation

swagger-codegen-maven-plugin in version 2.3.0-SNAPSHOT for typescript-angular with ngVersion=4

Steps to reproduce

Try to create a Configuration object which lazily refreshes the access_token (when the access_token has expired, but the refresh_token is still valid).

Related issues/PRs

I commented on a PR for the typescript-fetch client suggesting this feature a few weeks ago (this time I mean the angular2 client): #6130 (comment)
This PR also contains the new parameters for the accessToken function for the Typescript-Flow client (but does not return an Observable<string>): Configuration class changes in PR 6130

Suggest a fix/enhancement
  • Change the Configuration class to allow the access_token function to return an Observable<string>
  • Forward the name of the authorization scheme as well as the scope to the access_token function
  • Build the requestOptions asynchronously before executing the http request (flatMap the Observables)

I'm working on a PR right now, I just want to make sure that the feature would be accepted. :)

alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
Fix invalid auth header zip function (needs to return the resulting header for the next observable).
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
- Add missing rxjs operators
- Changed project name in package.json (seems like it's been overlooked after copy/pasting ng2 project)
- Update ts-ng2 & ts-ng4 petstore code (seems this hasn't been done the last time)
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
- Generate ts-ng2 security client (also contains some previous changes)
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
- Fix swagger annotations version in jaxrs-cxf-cdi pom after 2.0.0-rc1 release (maven doesn't know anything about rc versions - used 1.99 as a workaround)
- Re-generated the jaxrs-cxf-cdi client
@kenisteward
Copy link
Contributor

Hey you can do this without making changes! I'm sorry I missed this but if you do this in angular2

export function appApiConfigFactory() {
  return {};
}
    {
      provide: Configuration,
      useFactory: appApiConfigFactory,
      multi: false
    }, 

this will allow you anywher ein the code to inject the configuration object and change it at any point in time!

@alexrashed
Copy link
Author

This way I can easily exchange the configuration, but it doesn't really help me with updating my accessToken in case of a request (and an expired token), or am I wrong?

@kenisteward
Copy link
Contributor

export class Configuration {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | (() => string);
basePath?: string;
withCredentials?: boolean;
constructor(configurationParameters: ConfigurationParameters = {}) {
this.apiKeys = configurationParameters.apiKeys;
this.username = configurationParameters.username;
this.password = configurationParameters.password;
this.accessToken = configurationParameters.accessToken;
this.basePath = configurationParameters.basePath;
this.withCredentials = configurationParameters.withCredentials;
}
}

I am assuming you are storing the accessToken as a part of the configuration object. If this is so you can easily invalidate it with a AuthService you make in your Angular app by injecting Configuration and overwriting it with undefined and updating it by overwriting it with the new value.

What will happen is that value will ALWAYS be used since you've provided a non multi value in the providers. So that means all of the used Services that inject Configuration will have the same reference to that and anytime a request is made will use the new AccessToken.

I use this strategy for updating Username//Password when users login.

@kenisteward
Copy link
Contributor

The key is that it is all the same object as long as you setup your services in AppModule as they should be.

@alexrashed
Copy link
Author

I get what you mean, but my problem is not that I can't statically manage the accessToken, my problem of the lazy update of the accessToken still remains.
I actually want to respect the timeout of the accessToken and the refreshToken. So if the accessToken has expired, but the refreshToken is still valid (at the time of a new request) I want to refresh it on demand. But if the accessToken and the refreshToken are both invalid, the user session has ended and therefore the user has to be redirected back to the login.

I don't think I can implement this in a proper manner by just exchanging the Configuration in the CDI context. If it would be possible, could you give me a more advanced example?

alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 13, 2017
- Startover with a new branch after pr swagger-api#6493 was created on the wrong branch
- Handover authentication scheme name as well as the scopes to the accessToken function in the Configuration class
- accessToken returns an Observable to allow a lazy refresh of the accessToken
@kenisteward
Copy link
Contributor

As of Late in Angular 4, you can assign interceptors to every request. Event if not using angular 4 there are multiple libraries that do this.

https://angular.io/api/common/http/HttpInterceptor

You could easily have an interceptor that checks if a token is valid for a request and try to auto refresh it before you return the request to be made. I've actually done this is my code for our in house SSO setup.

@alexrashed
Copy link
Author

Yeah, I already evaluated that approach too. And I know that there are several possible ways to implement my requirement.
But in my opinion the cleanest solution is just to allow the accessToken function to be asynchronous. This accessToken refresh is just an obvious and nice use case (and what's the function for if not for something like that? everything else could be just as nicely done in a CDI factory). It also allows swagger-codegen to provide a standard-conform implementation of the oauth token refresh process as a default implementation of the Configuration sometime in the future.

alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Sep 27, 2017
- Startover with a new branch after pr swagger-api#6493 was created on the wrong branch
- Handover authentication scheme name as well as the scopes to the accessToken function in the Configuration class
- accessToken returns an Observable to allow a lazy refresh of the accessToken
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Oct 10, 2017
- Startover with a new branch after pr swagger-api#6493 was created on the wrong branch
- Handover authentication scheme name as well as the scopes to the accessToken function in the Configuration class
- accessToken returns an Observable to allow a lazy refresh of the accessToken
alexrashed added a commit to alexrashed/swagger-codegen that referenced this issue Oct 10, 2017
- Startover with a new branch after pr swagger-api#6493 was created on the wrong branch
- Handover authentication scheme name as well as the scopes to the accessToken function in the Configuration class
- accessToken returns an Observable to allow a lazy refresh of the accessToken
@alexrashed
Copy link
Author

I closed the PR, since there hasn't been any progress and it's heavily outdated. Therefore I'm closing this ticket too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants