Oauth2Flows example with OpenAPI generator

Are there any good examples of performing an oauth2 flow?

I can't for the life of me find any information on how to actually do this.

For reference, I'm using the OpenAPI generator with PetFinder's OpenAPI spec which uses the client credentials oauth2 flow (which can be found at the bottom of the page here )

I haven't used it myself, so can't vouch for it, but seems someone got it working with various APIs here: GitHub - luomein/authenticate-any-api

The page you linked shows an example of how to use your secrets to get a token using curl and how subsequent requests should provide this token in a request header.

I suggest you take a look at the example authentication middleware in the generator repo examples directory, which shows how to add a token to each request.

You’ll need to extend this solution to make the request if the token you have has expired and cache the new one.

I think you’re misunderstanding my original question.

I am aware of how to implement middleware that will add the access token to all my requests.

The problem is that the generated open api code doesn’t seem to expose any way for me to actually fetch the access token with my client secret and api key.

I am not that well versed in the openapi spec, but I think maybe Petfinder’s provided openapi spec is missing the access token endpoint.

Apologies for not understanding your question fully.

You’re right that the generated client doesn’t have a way of doing this for you.

The security key in the OpenAPI document is where API authors can include authentication methods. This document does state oauth2 but our generator doesn’t currently generate anything for this.

Your only option today is to hand roll this request in the middleware. Or provide the token by some other out of band method.

1 Like

I'd like to generate client code for an API with an OpenAPI 3.1 specification file, where the OAuth2 token authentication flow is being used. It looks like this is similar to what @BrentM was trying to achieve.

Am I correct to assume this is still an open issue (I have found this issue)?

Would the correct approach for the time being be to hand code the token request with URLSession and then implement a ClientMiddleware following the example client authentication middleware so I can use the generated code for the API with the obtained token as a Bearer token in the Authorization header?

1 Like

Yes, that's exactly right.

1 Like

Thanks! I was able to get my code to succesfully issue an authenticated request using the even simpler sample code from the ClientMiddleware documentation page.

Following either example, it looks like I would have to create a new Client once my token expires (in my case after 1h). Is this a valid approach? Or would you rather recommend doing something else?

That's one way, or the implementation of the middleware could be a class or an actor and handle the refreshing of the token internally. Either is fine.

1 Like

Thanks again! So while my code works now, I am also getting a number of validation warnings. including, but not limited to the /oaut2/token endpoint (which I am using with my hand-written code).

Are they expected with the current version of the Swift OpenAPI Generator, or is this something that needs to be addressed by the creators of the OpenAPI specification file? I have not used these other endpoints yet, but might have to.

warning: Validation warning: Inconsistency encountered when parsing `OpenAPI Schema`: Found schema attributes not consistent with the type specified: string. Specifically, attributes for these other types: ["object"]. [context: codingPath=.paths['/oauth2/token'].post.requestBody.content['application/x-www-form-urlencoded'].schema.properties.grant_type, contextString=, subjectName=OpenAPI Schema]
warning: Validation warning: Inconsistency encountered when parsing `OpenAPI Schema`: Found schema attributes not consistent with the type specified: string. Specifically, attributes for these other types: ["object"]. [context: codingPath=.paths['/users/link'].post.requestBody.content['application/json'].schema.properties.externalUserId, contextString=, subjectName=OpenAPI Schema]
warning: Validation warning: Inconsistency encountered when parsing `OpenAPI Schema`: Found schema attributes not consistent with the type specified: string. Specifically, attributes for these other types: ["object"]. [context: codingPath=.paths['/users/link'].post.requestBody.content['application/json'].schema.properties.language, contextString=, subjectName=OpenAPI Schema]
...

I'd need to see the OpenAPI doc to know for sure either way.

Would be great if you could have a look: link

So the warnings look correct.

For example, the schema for "grant_type" is "string", but contains the key "required", which isn't valid for string schemas. So the bug is on the side of whoever wrote the OpenAPI doc.

1 Like

FYI, with this info, they fixed the OpenAPI doc now :slight_smile:

1 Like

Are you utilizing the AAA package by luomein? If you are, how are you initializing it? Cant seem to get my smooth brain to figure that out.

No, I hand coded it. I've found the Kodeco Oauth tutorial useful, although a bit dated. Adapting it to SwiftUI WebAuthenticationSession and async / await was a good exercise.

In my Vapor app, for the API with the OpenAPI doc, I am reusing an URLSession based implementation which I had already built for iOS - their flow does not require a callback, just basic auth to get the token. For a second API I am using I re-implemented the authentication based on Vapor Client and replaced WebAuthenticationSession with a login request handler redirecting to the authentication provider and a callback request handler for the callback.