Skip to content

OAuth login first pass#2302

Closed
aglowinthefield wants to merge 2 commits intoModOrganizer2:masterfrom
aglowinthefield:feat/oauth2-login
Closed

OAuth login first pass#2302
aglowinthefield wants to merge 2 commits intoModOrganizer2:masterfrom
aglowinthefield:feat/oauth2-login

Conversation

@aglowinthefield
Copy link
Copy Markdown

No description provided.

@aglowinthefield aglowinthefield marked this pull request as ready for review November 14, 2025 16:33
@JonathanFeenstra
Copy link
Copy Markdown
Member

I'm getting build errors on this branch:

Image

Is this something wrong on my end? The CI build workflow didn't run, probably because this PR was initially a draft.

Comment thread src/CMakeLists.txt
categoryimportdialog
)

mo2_add_filter(NAME src/core GROUPS
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add the newly added source files to one of the source groups as well (either to this one or create a new group for all Nexus API-related stuff)?

Comment thread src/organizer_en.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We normally only stage the changes in this file when publishing new builds, so I think these should be reverted for this PR.

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 17, 2026

@aglowinthefield I know this PR is fairly old now but would you mind looking at Jon's suggestions?

I'm testing this locally now.

Copy link
Copy Markdown
Member

@Silarn Silarn left a comment

Choose a reason for hiding this comment

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

Ultimately I'm not sure this is actually functional. I don't believe the REST APIs can USE the OAuth token. I think we'd need to use the GraphQL API...

So this is at best a start to switching over to those APIs.

Comment thread src/nexusoauthlogin.h
void setState(State state, const QString& message = {});
void notifyTokens();
void handleError(const QString& message);
void injectPkceChallenge(QAbstractOAuth::Stage stage,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This appears to require an import of QAbstractOAuth

Comment thread src/nexusoauthlogin.cpp
QCryptographicHash::hash(m_codeVerifier, QCryptographicHash::Sha256)
.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);

parameters->insert(QStringLiteral("code_challenge"), QString::fromUtf8(challenge));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These should use replace instead of insert or you get repeat parameters.

Comment thread src/nexusoauthlogin.cpp
m_flow->setTokenUrl(QUrl(NexusOAuth::tokenUrl()));
#endif
m_flow->setClientIdentifier(clientId);
m_flow->setScope(QString());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It appears the scope can't be empty. Nexus seem to use "openid profile email"

Comment thread src/nexusoauthlogin.cpp
payload.insert(it.key(), QJsonValue::fromVariant(it.value()));
}

auto tokens = makeTokensFromResponse(payload);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unfortunately extraTokens isn't getting all the data - in fact only the created_at token. The refresh token and expiration are folded into the m_flow object and need to be retrieved with those methods. I haven't been able to get token type as of yet.

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 17, 2026

After some investigation, you can automatically fetch / create an application auth token by using the graphql api.

But none of that's been done yet. We'd need to authorize the oauth token, fetch the actual application apikey, and then use that at various points to authorize different GraphQL endpoints that need it.

I think the main benefit is being able to use collections but it's a bit of work to get this all functional for sure.

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 17, 2026

So, this is a functional way to retrieve an API key that can be used with the v1 API. I suppose a minimum viable version would use the OAuth credentials for fetch the API key at startup and then save the OAuth credentials with a refresh as needed. I haven't been able to test the refresh code yet.

Then we'd at least be part way to migrating to the v2 API and being able to potentially add collections.

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 17, 2026

After some more work, I was able to fetch an API key (I suppose I should verify the fallback autogenerate option) and use it to run the validation endpoint.

This endpoint specifically requires an application API key to validate against, so it makes sense it doesn't work with just the OAuth header.

However, once that bit is validated, the OAuth header does seem to work for the remaining APIs.

Comment thread src/nxmaccessmanager.cpp
bool ValidationAttempt::sendRequest(NXMAccessManager& m, const QString& key)
bool ValidationAttempt::sendRequest(NXMAccessManager& m, const NexusOAuthTokens& tokens)
{
const QString requestUrl(NexusBaseUrl + "/users/validate");
Copy link
Copy Markdown
Member

@Silarn Silarn Apr 17, 2026

Choose a reason for hiding this comment

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

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 18, 2026

https://github.com/ModOrganizer2/modorganizer/compare/dev/oauth-graphql is a functioning branch.

I'm not sure if I've had to refresh my token yet.

@Silarn
Copy link
Copy Markdown
Member

Silarn commented Apr 18, 2026

I'll note there's one snag with changing the validation endpoint. It doesn't have the API rate limit data which was causing mo2 to think it was out of requests. I modified it to use the default rate limits on validate and then it can get accurate limits when any other API request is triggered. Which works for now.

One thing I'm not sure about is what the rate limits look like for the graphql endpoints.

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.

3 participants