Skip to content

Keystone V3: Introduce OAuth1 auth support#1935

Merged
jtopjian merged 14 commits intogophercloud:masterfrom
kayrus:oauth
Apr 24, 2020
Merged

Keystone V3: Introduce OAuth1 auth support#1935
jtopjian merged 14 commits intogophercloud:masterfrom
kayrus:oauth

Conversation

@kayrus
Copy link
Copy Markdown
Contributor

@kayrus kayrus commented Apr 13, 2020

Resolves #1418

@jtopjian let me know if you find something wrong in this code before I start code cleanup.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 13, 2020

Coverage Status

Coverage increased (+0.05%) to 79.354% when pulling 15939e1 on kayrus:oauth into 456b0b6 on gophercloud:master.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 14, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 14, 2020

Build failed.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 14, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 14, 2020

@jtopjian done cleanup, ready for review.

Copy link
Copy Markdown
Contributor

@jtopjian jtopjian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kayrus Thank you for working on this.

This is a lot to take in and unfortunately I didn't have enough time to do a full review today. I've left two comments for now.

In addition, it looks like a lot of the opts structs are missing builder interfaces - we should probably include those.

I hope to have more time tomorrow to continue looking at this - I'm sorry about that.

if nonce == "" {
// when nonce is not set, generate a random one
query.Set("oauth_nonce", strconv.FormatInt(rand.Int63(), 10)+query.Get("oauth_timestamp"))
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an else here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but you pointed me to the fact, that there is no need to pass "nonce" as a parameter, since oauth_nonce is already parsed by gophercloud.BuildQueryString.

func stringToSign(method string, u string, params string) []byte {
parsedURL, _ := url.Parse(u)
if strings.HasPrefix(parsedURL.Host, "127.0.0.1") {
// Workaround for unit tests with dynamic ports
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to get around this by doing the following:

func TestAuthenticate(t *testing.T) {
  l, _ := net.Listen("tcp", "127.0.0.1:33199")
  th.Server = httptest.NewUnstartedServer(th.Mux)
  th.Server.Listener = l
  th.Server.Start()

  //th.SetupHTTP()
  defer th.TeardownHTTP()
  HandleAuthenticate(t)
...

However, the test is still failing, but I'm not sure why.

I'd definitely like to see this conditional removed somehow, though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an extra testhelper function to listen the static port. Additionally I noticed that using "https://identity:443/" URL containing the default port is not supported by oauth, therefore I modified the logic to normalize URLs with default port.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 15, 2020

In addition, it looks like a lot of the opts structs are missing builder interfaces - we should probably include those.

I don't think that build interface is necessary here. I don't expect that oauth method must be extended by additional parameters or logic.

I hope to have more time tomorrow to continue looking at this - I'm sorry about that.

No worries.

@kayrus kayrus force-pushed the oauth branch 3 times, most recently from 2ad403a to 7561bac Compare April 15, 2020 13:43
@jtopjian
Copy link
Copy Markdown
Contributor

I don't think that build interface is necessary here. I don't expect that oauth method must be extended by additional parameters or logic.

We should include the builder interfaces even if we can't think of a reason to use them. Any time in the past that I have assumed they wouldn't be used, someone usually reports how they're missing :)

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 15, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 15, 2020

We should include the builder interfaces even if we can't think of a reason to use them. Any time in the past that I have assumed they wouldn't be used, someone usually reports how they're missing :)

I need to rewrite existing logic, since opts.OAuthConsumerSecret and opts.OAuthTokenSecret are used inside Create funcs. This requires type assertion and I'd like to avoid this.

@jtopjian
Copy link
Copy Markdown
Contributor

Right, I see. I'm not trying to cause large rewrites, but I think if the Create function is tightly coupled to the opts structure, it might be another good indication that an interface is needed.

The interface methods can be pretty flexible with their return values, so that might be a way to link the Create function to the opts structure.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 15, 2020

@jtopjian As you mentioned Create function is tightly coupled to the opts structure. Therefore I used type assertion, because I have to, otherwise I cannot get an access to secrets.

As for the rest Create functions, done.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 15, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

@jtopjian the only way to properly introduce the build interface for Create function is to extend the tokens.AuthOptionsBuilder interface with ToTokenV3CreateHeaders(string, string) (map[string]string, error) method. What do you think?

@jtopjian
Copy link
Copy Markdown
Contributor

Could you create a new method to return the required information specific to this package?

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

@jtopjian Not sure if I understood you correctly, but see my latest commit.

@jtopjian
Copy link
Copy Markdown
Contributor

Yes, that should work.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

@jtopjian while I took a look on these interfaces. I noticed that there is no need to pass scope map into the ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) interface. We can call ToTokenV3ScopeMap method directly inside the ToTokenV3CreateMap method.
Thoughts?

UPD: Ignore my comment. It was done by purpose, since v3/tokens package passes scope, generated inside the v3/tokens package to gophercloud.AuthOptions.ToTokenV3CreateMap method.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 16, 2020

Build failed.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 16, 2020

recheck

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 16, 2020

Build succeeded.

@jtopjian
Copy link
Copy Markdown
Contributor

@kayrus Thank you for working on this. The general logic looks good and I appreciate the time you took investigating how to successfully generate oauth1-based requests.

I've done some refactoring to this which you can see here (jtopjian@5aad4d7). Let me know what you think.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 18, 2020

@jtopjian thanks for you time. I added my comments. Don't hesitate to commit directly to my branch to run the CI/CD pipeline next time. Github repo owners have this ability by default.

@jtopjian
Copy link
Copy Markdown
Contributor

Don't hesitate to commit directly to my branch to run the CI/CD pipeline next time.

Thanks for the review - I've made changes per your comments and will commit to this branch. I didn't want to do that initially until you had a first look.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 18, 2020

Build failed.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 19, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 19, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 19, 2020

@jtopjian rebased to master

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 20, 2020

@jtopjian can you hold with this PR? Considering the #1949 I'd like to introduce a proper logic to extract/parse the TokenResult. Otherwise if Extract() is not called, the response body will remain open.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 20, 2020

Build succeeded.

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 21, 2020

Build failed.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 21, 2020

recheck

@theopenlab-ci
Copy link
Copy Markdown

theopenlab-ci bot commented Apr 23, 2020

Build succeeded.

@kayrus
Copy link
Copy Markdown
Contributor Author

kayrus commented Apr 23, 2020

@jtopjian PR is ready

Copy link
Copy Markdown
Contributor

@jtopjian jtopjian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thank you!

@jtopjian jtopjian merged commit 105a969 into gophercloud:master Apr 24, 2020
@kayrus kayrus deleted the oauth branch April 24, 2020 05:46
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 this pull request may close these issues.

Auth: add OAuth authentication method

3 participants