Skip to content

Debug issue from gh440#444

Merged
pdecat merged 7 commits intoventh:masterfrom
erpel:debug-issue-from-gh440
Sep 8, 2025
Merged

Debug issue from gh440#444
pdecat merged 7 commits intoventh:masterfrom
erpel:debug-issue-from-gh440

Conversation

@erpel
Copy link
Copy Markdown
Contributor

@erpel erpel commented Aug 1, 2025

In #440 / #441 a callback was introduced. Using the response of the callback causes issues for our setup.
This MR is an attempt to debug the situation and hopefully finding a way that works for @thecaffiend as well as our setup.

@thecaffiend
Copy link
Copy Markdown
Contributor

Gave it a quick shot and I was able to go through the whole flow including duo push and get logged in. Unfortunately that's all I'll be able to get to today.

That said, there is an error in JSON decoding (that ends up getting ignored) that i have not looked into other than to see that it's happening in the try/except you added:

2025-08-05 09:44:43,644 [_duo_universal_prompt_authenticator _duo_universal_prompt_authenticator.py:_initiate_authentication] [543774-MainProcess] [140332594344640-MainThread] - ERROR: Error doing callback
Traceback (most recent call last):
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-erpel/lib/python3.11/site-packages/requests/models.py", line 976, in json
    return complexjson.loads(self.text, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-erpel/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-erpel/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-erpel/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/lp76/development/adfs/erpel-aws-adfs/aws_adfs/_duo_universal_prompt_authenticator.py", line 508, in _initiate_authentication
    callback_json = callback_response.json()
                    ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-erpel/lib/python3.11/site-packages/requests/models.py", line 980, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2025-08-05 09:44:43,646 [_duo_universal_prompt_authenticator _duo_universal_prompt_authenticator.py:_initiate_authentication] [543774-MainProcess] [140332594344640-MainThread] - ERROR: ignoring: Expecting value: line 1 column 1 (char 0)
2025-08-05 09:44:43,646 [_duo_universal_prompt_authenticator _duo_universal_prompt_authenticator.py:_initiate_authentication] [543774-MainProcess] [140332594344640-MainThread] - INFO: after callback
Waiting for additional authentication
Triggering authentication method: 'Duo Push' with 'phone1'

Again, it ultimately lets me in with a push even with the above error.

@erpel
Copy link
Copy Markdown
Contributor Author

erpel commented Aug 5, 2025

I get the same error - initially I thought it happened because I used the wrong response for it. Since I can reproduce with our setup as well - I can try to debug this.

It would be nice if we could get the trace (run with debug logging) of the http request just before this error happens. Would be interesting to see the comparison between our two environments. - I think the error happening does mean, that it should work for your setup even if nothing is done with the response from this callback. I'll try to add a few command line switches or sth. to let us experiment with different procedures without requiring code changes every time.

Thanks for taking the time to test this.

@thecaffiend
Copy link
Copy Markdown
Contributor

Sure, np. You just looking for the block starting with something like [_duo_universal_prompt_authenticator _duo_universal_prompt_authenticator.py:_initiate_authentication] [xxxxxx-MainProcess] [xxxxxxxxxxxxxxxx-MainThread] and up to the error, or less/more than that?

@erpel
Copy link
Copy Markdown
Contributor Author

erpel commented Aug 18, 2025

That would be sufficient. I tried to reproduce the issue somewhat and improve logging but could not reproduce this anymore.
Testing on the latest branch would be terrific but I don't see significant changes to what you tested with.

I'd be looking for this part specifically, to understand why the response is not parsable as json "sometimes":

 ================================================================================
Request:
* url: https://api-273...
* headers: {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'text/plain, */*; q=0.01', 'Connection': 'keep-alive', 'Accept-Language': 'en', 'Cookie': 'hac|DUSZFI323T1KW0CARLIX|x="x==|1755507941|x"'}
* body: None
================================================================================
Response:
* status: 200
* headers: {'Server': 'Duo/1.0', 'Date': 'Mon, 18 Aug 2025 11:01:58 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Cache-Control': 'no-store', 'Pragma': 'no-cache', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'P3p': 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"', 'Origin-Trial': 'AhDE/x+xbc/x==', 'Etag': 'W/"94ee09d3471aex7cd5d8f3a9a9f"', 'Set-Cookie': 'sid|678b69e6-b12e-4b71-b295x481f19a"; expires=Mon, 18 Aug 2025 11:16:58 GMT; HttpOnly; Path=/; SameSite=None; Secure, _xsrf|678b69e6-b12e-4b71-b295-83a8c54c10f7="ZmQ5ZDx702d071e9919cf1fd7020"; expires=Mon, 18 Aug 2025 12:31:58 GMT; HttpOnly; Path=/; SameSite=None; Secure', 'Strict-Transport-Security': 'max-age=31536000', 'Content-Security-Policy': "default-src 'self'; frame-src 'self' ; img-src 'self'  ; connect-src 'self'     ", 'X-Content-Type-Options': 'nosniff', 'Content-Encoding': 'gzip'}
* body: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
…

@thecaffiend
Copy link
Copy Markdown
Contributor

Here you go

================================================================================
Request:
* url: https://api-4b...
* headers: {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, zstd', 'Accept': 'text/plain, */*; q=0.01', 'Connection': 'keep-alive', 'Accept-Language': 'en', 'Cookie': '_xsrf|xxx|xxx|xxx"; hac|xxx|xxx|xxx|xxx"; sid|xxx|xxx|xxx"'}
* body: None
================================================================================
Response:
* status: 200
* headers: {'Server': 'Duo/1.0', 'Date': 'Sat, 23 Aug 2025 15:12:30 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Cache-Control': 'no-store', 'Pragma': 'no-cache', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'P3p': 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"', 'Origin-Trial': 'xxx', 'Etag': 'W/"xxx"', 'Strict-Transport-Security': 'max-age=31536000', 'Content-Security-Policy': "xxx", 'X-Content-Type-Options': 'nosniff', 'Content-Encoding': 'gzip'}
* body: <!DOCTYPE html>
<!--[if IE 8]> <html lang="en" class="ie ie8"> <![endif]-->
<!--[if IE 9]> <html lang="en" class="ie ie9"> <![endif]-->
<!--[if gt IE 9]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">

<!-- Set latest compatibility for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">

<title>
Two-Factor Authentication
</title>
<!-- Import for all versions of IE, in case the standards mode is downgraded to IE8 -->
<!--[if IE]> <link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;css&#x2f;v3&#x2f;ie8.css&#x3f;v&#x3d;e9b26"> <![endif]-->

<link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;css&#x2f;normalize.css&#x3f;v&#x3d;a674e">
<link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;fonts&#x2f;ss-standard&#x2f;ss-standard.css&#x3f;v&#x3d;a8885">
<link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;css&#x2f;fonts&#x2f;duo-admin.css&#x3f;v&#x3d;50a8a">
<link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;css&#x2f;v3&#x2f;base.css&#x3f;v&#x3d;9a14c">

<link rel="stylesheet" href="&#x2f;frame&#x2f;static&#x2f;css&#x2f;tipsy.css&#x3f;v&#x3d;4217a">


</head>
<body>
<div class="oidc-wrapper">
<div class="base-wrapper ">

<div class="base-main">
<div role="main" class="base-body">

<form action="/frame/prompt" method="post" id="login-form" class="inline login-form hidden">
<input type="hidden" name="sid" value="xxx">
<input type="hidden" name="url" value="/frame/prompt">
<input type="hidden" name="enrollment_message" value="">
<input type="hidden" name="itype" value="adfs">

<input type="hidden" name="_xsrf" value="xxx" />

<input type="hidden" name="ukey" value="xxx">

<input type="hidden" name="out_of_date" value="False">
<input type="hidden" name="days_out_of_date" value="0">
<input type="hidden" name="should_update_dm" value="False">


<input type="hidden" name="preferred_factor" value="">
<input type="hidden" name="preferred_device" value="">

<input type="hidden" name="days_to_block" value="None">
<input type="hidden" name="should_retry_u2f_timeouts" value="True">

<input type="hidden" name="has_ssp_shutoff_feature" value="False">


<input type="hidden" id="has_phone_that_requires_compliance_text" name="has_phone_that_requires_compliance_text" value="False">

<fieldset class="device-selector ">
<h1 class="cramped-frame-view">
Device&#x3a;
</h1>
<div class="device-select-wrapper">
<select name="device" aria-label="Device" tabindex=2>

<option value="phone1">xxx;</option>

<option value="phone2">xxx;</option>

</select>

</div>
</fieldset>

<div id="auth_methods">

<fieldset data-device-index="phone1" class="hidden">
<h2 class="medium-or-larger auth-method-header">
Choose an authentication method
</h2>


<div class="row-label push-label">
<input type="hidden" name="factor" value="Duo&#x20;Push">
<span class="label factor-label">
<i class="icon-smartphone-check"></i>
Duo Push

<small class="recommended">
Recommended
</small>

</span>
<button tabindex="2" type="submit" class="positive&#x20;auth-button" ><!-- -->Send Me a Push </button>
</div>

<div class="row-label phone-label">
<input type="hidden" name="factor" value="Phone&#x20;Call">
<span class="label factor-label">
<i class="icon-call-ringing" alt="" role="presentation"></i>
Call Me

</span>
<button tabindex="2" type="submit" class="positive&#x20;auth-button" ><!-- -->Call Me </button>
</div>

<div class="passcode-label row-label">
<input type="hidden" name="factor" value="Passcode">
<span class="label factor-label">
<i class="icon-smartphone-ellipsis" alt="" role="presentation"></i>
Passcode
</span>
<div class="passcode-input-wrapper">
<input type="text" name="passcode" autocomplete="off" data-index="phone1" class="hidden passcode-input" placeholder="ex.&#x20;867539" aria-label="passcode" tabindex=2>
<div class="next-passcode-msg" role="alert" aria-live="polite"></div>
</div>
<button tabindex="2" type="submit" id="passcode" class="positive&#x20;auth-button" ><!-- -->Enter a Passcode </button>
<input name="phone-smsable" type="hidden" value="False" />
<input name="mobile-otpable" type="hidden" value="True" />
<input name="next-passcode" type="hidden" value="1" />
</div>

</fieldset>

<fieldset data-device-index="phone2" class="hidden">
<h2 class="medium-or-larger auth-method-header">
Choose an authentication method
</h2>


<div class="row-label push-label">
<input type="hidden" name="factor" value="Duo&#x20;Push">
<span class="label factor-label">
<i class="icon-smartphone-check"></i>
Duo Push


<small class="recommended">
Recommended
</small>


</span>
<button tabindex="2" type="submit" class="positive&#x20;auth-button" ><!-- -->Send Me a Push </button>
</div>




<div class="row-label phone-label">
<input type="hidden" name="factor" value="Phone&#x20;Call">
<span class="label factor-label">
<i class="icon-call-ringing" alt="" role="presentation"></i>
Call Me

</span>
<button tabindex="2" type="submit" class="positive&#x20;auth-button" ><!-- -->Call Me </button>
</div>

<div class="passcode-label row-label">
<input type="hidden" name="factor" value="Passcode">
<span class="label factor-label">
<i class="icon-smartphone-ellipsis" alt="" role="presentation"></i>
Passcode
</span>
<div class="passcode-input-wrapper">
<input type="text" name="passcode" autocomplete="off" data-index="phone2" class="hidden passcode-input" placeholder="ex.&#x20;867539" aria-label="passcode" tabindex=2>
<div class="next-passcode-msg" role="alert" aria-live="polite"></div>
</div>
<button tabindex="2" type="submit" id="passcode" class="positive&#x20;auth-button" ><!-- -->Enter a Passcode </button>
<input name="phone-smsable" type="hidden" value="False" />
<input name="mobile-otpable" type="hidden" value="True" />
<input name="next-passcode" type="hidden" value="None" />
</div>

</fieldset>

<input type="hidden" name="has-token" value="false">

</div>

<div>

<div class="stay-logged-in">
<label class="remember_me_label_field">
<input type="checkbox"
name="dampen_choice"
value="1" tabindex="2">
<span id="remember_me_label_text">
Remember me for 7 days
</span>
</label>
<input type="hidden" name="cookies_allowed" value="">
</div>

</div>
</form>
 
<form class="oidc-exit-form" action="/frame/prompt/oidc/exit" method="POST">
<input type="hidden" name="txid" value="" />
<input type="hidden" name="sid" value="xxx" />
<input type="hidden" name="_xsrf" value="xxx" />
</form>


</div>
</div>
<div class="base-navigation">

<div class="base-navigation">
<div role="banner">

<a href="&#x2f;frame&#x2f;prompt&#x3f;sid&#x3d;xxx">
<img src="&#x2f;frame&#x2f;logo&#x3f;sid&#x3d;xxx" alt="xxx" width="128"/>
</a>

</div>
<div class="help-sidebar">
<button class='btn btn-support'>
<i class="icon-align-justify" aria-label="Open"></i>
<i class="icon-delete" aria-label="Close"></i>
Settings
</button>
<div class="help-links">
<nav role="navigation">

<a id="help_link" class="help-nav" href="https&#x3a;&#x2f;&#x2f;guide.duo.com&#x2f;traditional-prompt" target="_blank" aria-label="What&#x20;is&#x20;the&#x20;Duo&#x20;Prompt&#x3f;&#x20;&#x28;Opens&#x20;in&#x20;a&#x20;new&#x20;tab.&#x29;">
What is this&#x3f;<i class="icon-new-window"></i>
</a>



<a class="help-nav device-page-link" id="new-device" href="/frame/enroll/pre_flow_prompt?sid=xxx&post_auth_action=addDevice">
Add a new device
</a>
<a class="help-nav device-page-link" href="/frame/enroll/pre_flow_prompt?sid=xxx&post_auth_action=manageDevices">
My Settings &amp; Devices
</a>

<a href="#" class="need-help">Need help&#x3f;</a>
</nav>

<div role="contentinfo">
<a href="https&#x3a;&#x2f;&#x2f;duo.com" class="branding-link" target="_blank" rel="noreferrer noopener">
Secured by Duo
</a>
</div>

</div>

</div>
<div class="help-overlay offscreen">
<div class="help-links">
<nav role="navigation">

<a id="help_link" class="help-nav" href="https&#x3a;&#x2f;&#x2f;guide.duo.com&#x2f;traditional-prompt" target="_blank" aria-label="What&#x20;is&#x20;the&#x20;Duo&#x20;Prompt&#x3f;&#x20;&#x28;Opens&#x20;in&#x20;a&#x20;new&#x20;tab.&#x29;">
What is this&#x3f;<i class="icon-new-window"></i>
</a>


<a class="help-nav device-page-link" id="new-device" href="/frame/enroll/pre_flow_prompt?sid=xxx&post_auth_action=addDevice">
Add a new device
</a>
<a class="help-nav device-page-link" href="/frame/enroll/pre_flow_prompt?sid=xxx&post_auth_action=manageDevices">
My Settings &amp; Devices
</a>


<a href="#" class="need-help">Need help&#x3f;</a>
</nav>

<div role="contentinfo">
<a href="https&#x3a;&#x2f;&#x2f;duo.com" class="branding-link" target="_blank" rel="noreferrer noopener">
Secured by Duo
</a>
</div>


</div>

</div>
</div>

</div>
<div class="base-sidebar">

</div>
<div id="messages-view" class="hidden">
<div class="messages-list">

</div>
</div>


</div>
</div>
<script id="translations" type="text/json">
{"locale_data": {"js-messages": {"": {"domain": "js-messages", "lang": "en", "plural_forms": "nplurals&#x3d;2&#x3b; plural&#x3d;&#x28;n &#x21;&#x3d; 1&#x29;&#x3b;"}}}, "domain": "js-messages"}
</script>


<!-- Hidden XSRF input needed for POST requests made by errors.js -->
<input type="hidden" name="_xsrf" value="xxx" />

<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;jquery&#x2f;jquery-prologue.js&#x3f;v&#x3d;400dc"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;jquery&#x2f;jquery.min.js&#x3f;v&#x3d;ff152"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;he&#x2f;he.min.js&#x3f;v&#x3d;aaa33"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;lib&#x2f;jquery-postmessage.min.js&#x3f;v&#x3d;98c73"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;lodash&#x2f;lodash.min.js&#x3f;v&#x3d;6585f"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;backbone&#x2f;backbone-min.js&#x3f;v&#x3d;e0ff6"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;page&#x2f;v3&#x2f;frame.js&#x3f;v&#x3d;b5aee"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;page&#x2f;v3&#x2f;base.js&#x3f;v&#x3d;4ef4f"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;validator&#x2f;validator.min.js&#x3f;v&#x3d;9a068"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;lib&#x2f;jquery&#x2f;jquery-epilogue.js&#x3f;v&#x3d;c4ac5"></script>
<script id="browser_exceptions" src="&#x2f;frame&#x2f;static&#x2f;shared&#x2f;js&#x2f;errors.js&#x3f;v&#x3d;d10d2" data-url="/frame/browser_exceptions"></script>
<input type="hidden" name="helpdesk-message" id="helpdesk-message" value="&quot;&quot;" />
<!--[if lt IE 10]>
<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;page&#x2f;v3&#x2f;quirks.js&#x3f;v&#x3d;0cb70"></script>
<![endif]-->


<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;lib&#x2f;jquery.tipsy.js&#x3f;v&#x3d;c0432"></script>
<script src="&#x2f;frame&#x2f;static&#x2f;js&#x2f;page&#x2f;v3&#x2f;prompt.js&#x3f;v&#x3d;fbe3f"></script>


</body>
</html>

================================================================================
            
2025-08-23 11:12:30,612 [_duo_universal_prompt_authenticator _duo_universal_prompt_authenticator.py:_initiate_authentication] [541265-MainProcess] [140639716917952-MainThread] - ERROR: Error doing callback
Traceback (most recent call last):
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-dev/lib/python3.10/site-packages/requests/models.py", line 976, in json
    return complexjson.loads(self.text, **kwargs)
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-dev/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-dev/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-dev/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/lp76/development/adfs/erpel-aws-adfs/aws_adfs/_duo_universal_prompt_authenticator.py", line 509, in _initiate_authentication
    callback_json = callback_response.json()
  File "/home/lp76/.local/share/mamba/envs/aws-adfs-dev/lib/python3.10/site-packages/requests/models.py", line 980, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

@erpel
Copy link
Copy Markdown
Contributor Author

erpel commented Aug 29, 2025

Thanks for the confirmation. Seems in your case, the callback returns a webpage instead of json.
I've updated the code to check content type of the response. This should log you in without errors - but it also means that for your use case nothing needs to be done with the response.
Unless we find a situation in which the response is needed, I find it really hard to imagine why it's needed in the first place.

Anyhow, if this works for both our setups, it's time to start discussion with maintainers if any of this approach can be accepted.

It would be quite awesome to have a few "supported" setups of AD FS + other services in some test environment, but I guess the cost and effort to maintain a windows environment + bunch of other SaaS is beyond what most could contribute.

@thecaffiend
Copy link
Copy Markdown
Contributor

Pulled and seems to be working here. I'll get another tester onboard, but expect the same results.

@erpel erpel mentioned this pull request Sep 2, 2025
@pdecat pdecat added the python Pull requests that update Python code label Sep 2, 2025
Comment thread aws_adfs/commands.py Outdated
Comment thread aws_adfs/_duo_authenticator.py Outdated
Comment thread aws_adfs/_duo_authenticator.py Outdated
Comment thread aws_adfs/_duo_universal_prompt_authenticator.py Outdated
Comment thread aws_adfs/account_aliases_fetcher.py Outdated
erpel and others added 2 commits September 3, 2025 09:09
Co-authored-by: Patrick Decat <pdecat@gmail.com>
Use raw string for regex.
@pdecat
Copy link
Copy Markdown
Collaborator

pdecat commented Sep 5, 2025

Ok to merge and release this when you are ready.

@erpel
Copy link
Copy Markdown
Contributor Author

erpel commented Sep 8, 2025

For me it looks good, then our users can install the latest version again.

@pdecat pdecat merged commit 65a2ff4 into venth:master Sep 8, 2025
16 checks passed
@pdecat
Copy link
Copy Markdown
Collaborator

pdecat commented Sep 8, 2025

Released in https://github.com/venth/aws-adfs/releases/tag/v2.12.1

@erpel erpel deleted the debug-issue-from-gh440 branch September 9, 2025 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants