Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Mailer] Improve oauth setup#52585

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
dbu wants to merge2 commits intosymfony:7.4
base:7.4
Choose a base branch
Loading
fromdbu:mailer-oauth
Open

Conversation

dbu
Copy link
Contributor

@dbudbu commentedNov 14, 2023

QA
Branch?7.1
Bug fix?no
New feature?yes
Deprecations?no
Issues-
LicenseMIT

Setting up the Symfony Mailer with XOAuth based authentication is possible but quite complicated. I hacked something together inhttps://gist.github.com/dbu/3094d7569aebfc94788b164bd7e59acc but with a few changes, I would only need to implement the token provider and configure it.

I guess this is too late for 7.0, so it should go to 7.1. I will adjust the target branch once 7.1 is created.

OskarStark and garak reacted with thumbs up emoji
@carsonbot
Copy link

Hey!

Thanks for your PR. You are targeting branch "7.0" but it seems your PR description refers to branch "7.1".
Could you update the PR description or change target branch? This helps core maintainers a lot.

Cheers!

Carsonbot

foreach ($config['smtp']['authenticators'] ?? [] as $authenticator) {
$authenticators[] = new Reference($authenticator);
}
$container->getDefinition('mailer.transport_factory.smtp')->setArgument(3, $authenticators);
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

according tomailer_transport.php this service is the EsmtpTransportFactory, but the CI tells that we somehow end up setting an argument to "Symfony\Component\Mailer\Mailer" - any idea what i am messing up here?

Copy link
Member

Choose a reason for hiding this comment

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

the weird error message could be because of inlining the transport factory services. It might be inside one of the inlined services inside the mailer service.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

is that a bug of the DI container, or should i be doing something differently?

Copy link
Member

Choose a reason for hiding this comment

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

I would not call it a bug. The hard thing is that inline definitions don't have an id. So that's hard to know how to mention them in error messages.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

if it is not a bug, what do i need differently to set the parameter on the correct place?

@nicolas-grekasnicolas-grekas modified the milestones:7.0,7.1Nov 17, 2023
@carsonbotcarsonbot changed the titleimprove oauth setup for mailer[Mailer] improve oauth setup for mailerNov 17, 2023
@nicolas-grekasnicolas-grekas changed the title[Mailer] improve oauth setup for mailer[Mailer] Improve oauth setupNov 17, 2023
@nicolas-grekasnicolas-grekas changed the base branch from7.0 to7.1November 17, 2023 15:56
@nicolas-grekas
Copy link
Member

Did you consider adding the oauth token providen to core? Could this be done instead of the current extra interface? Is there an approach that wouldn't require adding this extra interface - or at least makingXOAuth2Authenticator unaware of it? I don't really like the instanceof check there 😬

@dbu
Copy link
ContributorAuthor

dbu commentedNov 20, 2023
edited
Loading

Did you consider adding the oauth token providen to core? Could this be done instead of the current extra interface? Is there an approach that wouldn't require adding this extra interface - or at least making XOAuth2Authenticator unaware of it?

oauth seems to be more of a concept than an actual standard. every provider is doing it differently. if symfony had a fully fledged oauth component with support for all the major players, we could maybe make this use that. but to me an interface is really the way to go here.

oauth means sending a post with some json body to some url. but which field names to use, whats required or optional and what values to use e.g. for the scope is totally provider dependent.

for office365/exchange, the values happen to be

    private const OAUTH_URL = 'https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token';    private const SCOPE = 'https://outlook.office365.com/.default';    private const GRANT_TYPE = 'client_credentials';        $data = [            'client_id' => $this->clientId,            'client_secret' => $this->clientSecret,            'scope' => self::SCOPE,            'grant_type' => self::GRANT_TYPE,        ];    // post that as x-www-form-urlencoded to    UriTemplate::expand(self::OAUTH_URL, [            'tenant' => $this->tenant,    ]));

I don't really like the instanceof check there 😬

i think the null check is required for BC.

@nicolas-grekas
Copy link
Member

Sorry I wrote "instanceof" but that's inaccurate. I meant this line:
https://github.com/symfony/symfony/pull/52585/files#diff-3ac0365eb0e52c96210c4fc1848acd4be3eb71ceb86aed561b76b8d1d3626b6dR42

dbu reacted with thumbs up emoji

@@ -32,6 +39,7 @@ public function getAuthKeyword(): string
*/
public function authenticate(EsmtpTransport $client): void
{
$client->executeCommand('AUTH XOAUTH2 '.base64_encode('user='.$client->getUsername()."\1auth=Bearer ".$client->getPassword()."\1\1")."\r\n", [235]);
$token = $this->tokenProvider ? $this->tokenProvider->getToken() : $client->getPassword();

Choose a reason for hiding this comment

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

Suggested change
$token =$this->tokenProvider ?$this->tokenProvider->getToken() :$client->getPassword();
$token =$this->tokenProvider?->getToken() :$client->getPassword();

But I'm wondering about this line as now we give two ways to pass that secret - what if both are set for example? I feel like it'd be better to provide only one way to pass that secret - the existing one if possible :) Does that make sense? (it doesn't have to :) )

Copy link
Member

Choose a reason for hiding this comment

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

the issue with the existing one is that oauth tokens tend to be short-lived. In your worker process, you cannot just set the token as the password in the Transport as this will not properly refresh it when it expires.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

changing the client to fetch the password dynamically would be a large refactor, and would mix responsibilities for the auth method.

the thing is that an oauth token can not be statically configured. and in a long running process it might expire before the process ends, so each time we need it we need to be ready to re-fetch it.

we could inject some TokenProviderInterface into the client and use that for getPassword(), but i don't think that would be better.

…ticator.phpCo-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

Got it for the geToken??getPassword logic, makes sense to me now.
Here are some suggestions to help move forward.

@@ -2091,6 +2091,15 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl
->end()
->end()
->end()
->arrayNode('smtp')
->fixXmlConfig('authenticator')

Choose a reason for hiding this comment

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

instead of adding a new config entry, I'd suggest passing a tagged_locator in the service definition
we should define the default authenticators as services with low priority so that then adding a new authenticator is just a matter of creating a new class that implements AuthenticatorInterface, thanks to registerForAutoconfiguration.

* Usually with OAuth, you will need to do some web request to fetch the token.
* You also want to cache the token for as long as it is valid.
*/
interface AuthTokenProviderInterface

Choose a reason for hiding this comment

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

TokenProviderInterface?

/**
* @param AuthenticatorInterface[]|null $authenticators
*/
public function __construct(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null, array $authenticators = null)

Choose a reason for hiding this comment

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

I'm not sure we need the new argument: calling setAuthenticators on the resulting instance should be enough

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedNov 30, 2023
edited
Loading

Note that it'd be cool to contribute the office365 bridge while at it :)

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedNov 30, 2023
edited
Loading

Oh and maybe also an AbstractOauthTokenProvider?

@dbu
Copy link
ContributorAuthor

dbu commentedDec 13, 2023

thanks for the feedback. yeah that sounds good. i will try to find time, might be after christmas only 🙈

the office365 provider would go into a new Office365 namespace athttps://github.com/symfony/symfony/tree/7.1/src/Symfony/Component/Mailer/Bridge and need a composer.json for the subtree split, right?

i will see if an abstract base class makes sense that could be shared in the messenger package.

@nicolas-grekas
Copy link
Member

the office365 provider would go into a new Office365 namespace

yes!

@pounard
Copy link
Contributor

Hello,@dbu@nicolas-grekas, I stumbled here while doing some research, because I am since a few days working a new component proposal, that does exactly the job of the introduced hereAuthTokenProvider, and more. Would you be interested in participating instead of adding this new interface in this PR ?

@dbu
Copy link
ContributorAuthor

dbu commentedFeb 15, 2024

i do not have much time at the moment, so more than glad if you put some brain energy into proposing a nice architecture for the auth token system. i can try to give my input on the proposal when you have a draft ready, and will be happy to rebase this PR when/if your proposal gets merged.

pounard reacted with thumbs up emoji

@pounard
Copy link
Contributor

@dbu thanks, I will in few days I hope, open an issue for it.

@pounard
Copy link
Contributor

@dbu if you have a few minutes to spare, I'd very much like to have your sentiment about#54013, thanks in advance !

@pounard
Copy link
Contributor

pounard commentedFeb 20, 2024
edited
Loading

Did you consider adding the oauth token providen to core?

@nicolas-grekas I did ! Please see my PR#54013 - your insights would be invaluable !

@xabbuhxabbuh modified the milestones:7.1,7.2May 15, 2024
@fabpotfabpot modified the milestones:7.2,7.3Nov 20, 2024
@fabpotfabpot modified the milestones:7.3,7.4May 26, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@nicolas-grekasnicolas-grekasnicolas-grekas left review comments

@stofstofstof left review comments

Assignees
No one assigned
Projects
None yet
Milestone
7.4
Development

Successfully merging this pull request may close these issues.

7 participants
@dbu@carsonbot@nicolas-grekas@pounard@stof@fabpot@xabbuh

[8]ページ先頭

©2009-2025 Movatter.jp