Comments (10)
Thank you very much again for taking the time to help me integrate with my odd auth-endpoint. I am able to authenticate with ADFS using a custom strategy, containing bits and pieces of the code you provided.
I very much appreciate your efforts, thanks again.
from assent.
I see that i tries to fetch the access_token, but the access_token was already in the params of the first callback, so I guess, it's technically not a full authorization code flow?
I tried several combinations, this is what it's at and i am happy it reaches the callback in the Authorization-Controller...
authorization_params: [
response_type: "token id_token code",
resource: "xxx",
grant_type: "authorization_code",
response_mode: "form_post"
],
from assent.
Transferred to assent repo, as it is indeed an assent issue.
Are you using :client_secret_post
auth method rather than :client_secret_basic
? With :client_secret_basic
the authorization header is base64 encoded: https://github.com/pow-auth/assent/blob/v0.1.4/lib/assent/strategies/oauth2.ex#L142-L152
Also FYI the next release of PowAssent will have built-in support for POST callback, though adding a POST route is pretty much the same thing.
from assent.
Thank you for your feedback. I played around with it some more and I have two notable points:
-
I only get the original error, when I use no
auth_method
or:client_secret_basic
. (even tho I see it clearly done in the code you linked). when using e.g.:client_secret_jwt
, it complains about invalid credentials, which leads me to point 2. -
I don't have a client_secret for this provider, but it seems, that I don't need one, as I get the access_token I want in the very first callback.
it's as if it needed another implementation for get_access_token
with a different match, something like:
defp get_access_token(config, %{"acccess_token" => token}) do
which returns/uses the token directly, when its in the params. but i am just guessing here.
I am using a CustomProvider with use Assent.Strategy.OAuth2.Base
.
I return the following (redacted) config from default_config
:
[
client_id: "redacted guid",
client_secret: "",
auth_method: :client_secret_jwt,
site: "https://login.redacted.com/adfs",
authorize_url: "https://login.redacted.com/adfs/oauth2/authorize",
token_url: "https://login.redacted.com/adfs/oauth2/token",
authorization_params: [
response_type: "token id_token code", //<-- here asking for ALL the codes
resource: "redacted guid",
grant_type: "password", //or authorization_code
response_mode: "form_post" //this is needed, no luck with :query or :fragment
],
resource: "same redacted guid as above",
nonce:
16
|> :crypto.strong_rand_bytes()
|> Base.encode64(padding: false), //had `true` here as well
strategy: Assent.Strategy.OAuth2
]
from assent.
Yeah, you are right that no secret should be used, I'll relax the OAuth2 client to not use any auth method if there is no :auth_method
defined.
In the meanwhile, could you try use :client_secret_post
as the :auth_method
? It seems that it's the way to deal with it: https://github.com/nordvall/TokenClient/wiki/OAuth-2-Authorization-Code-grant-in-ADFS
Your config also seems to mix in some OIDC stuff, that isn't used or necessary in OAuth 2.0. This should be enough for OAuth 2.0:
[
client_id: "redacted guid",
client_secret: "",
auth_method: :client_secret_post,
site: "https://login.redacted.com/adfs",
authorize_url: "oauth2/authorize",
token_url: "oauth2/token",
authorization_params: [
response_type: "code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: Assent.Strategy.OAuth2
]
But you can also use Assent.Strategy.OIDC
instead:
[
client_id: "redacted guid",
client_secret: "",
auth_method: :client_secret_post,
site: "https://login.redacted.com/adfs",
authorization_params: [
response_type: "id_token code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: Assent.Strategy.OIDC
]
from assent.
Just added a fix in #24. Try use the master branch of assent in mix.exs
: {:assent, github: "pow-auth/assent", override: true}
.
And use this config setting:
[
client_id: "redacted guid",
site: "https://login.redacted.com/adfs",
authorize_url: "oauth2/authorize",
token_url: "oauth2/token",
authorization_params: [
response_type: "code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: Assent.Strategy.OAuth2
]
Or if you wish to use OIDC:
[
client_id: "redacted guid",
site: "https://login.redacted.com/adfs",
authorization_params: [
response_type: "id_token code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: Assent.Strategy.OIDC
]
from assent.
Very cool, thank you. I did as you suggested and I am now getting the following error:
Assent.Config.MissingKeyError at POST /auth/schultzer/callback
Key `:user_url` not found in config
This information I don't have (this is a URL at the Auth-Providers site, right?). Maybe I can find it, though, I'll keep searching... but I should not actually be storing any user-identifying information.
When I try OIDC, it behaves a bit like before, asking for the :user_secret, when I supply an empty one, it complains about the Base64-encoding.
But I was able to work around it by providing my own (horrible) strategy:
the gist:
def authorize_url(config) do
with {:ok, redirect_uri} <- Keyword.fetch(config, :redirect_uri),
{:ok, site} <- Keyword.fetch(config, :site),
{:ok, client_id} <- Keyword.fetch(config, :client_id) do
state = gen_state()
params = authorization_params(config, client_id, state, redirect_uri)
authorize_url = Keyword.get(config, :authorize_url, "/oauth/authorize")
url = to_url(site, authorize_url, params)
{:ok, %{url: url, session_params: %{state: state}}}
end
end
defp authorization_params(config, client_id, state, redirect_uri) do
params = Keyword.get(config, :authorization_params, [])
[response_type: "access_token", client_id: client_id, state: state, redirect_uri: redirect_uri]
|> Keyword.merge(params)
|> List.keysort(0)
end
def callback(config, params, strategy \\ __MODULE__) do
token = params["access_token"]
{:ok, claims} = Joken.peek_claims(token)
{:ok, %{user: claims, token: claims}}
end
Not sure, if I return the right stuff, tho...
from assent.
Oh right, the assent strategies expects a user url so the user info can be fetched.
You can create a custom provider module that overrides the get_user/2
method. This is how the user is fetched using the id_token
with OIDC:
defmodule MyApp.ADFS do
use Assent.Strategy.OIDC.Base
@impl true
def default_config(config) do
[
site: "https://login.redacted.com/adfs",
authorization_params: [
response_type: "id_token code",
response_mode: "form_post"
]
]
end
@impl true
def normalize(_config, user), do: {:ok, user}
@impl true
def get_user(config, token) do
case Helpers.verify_jwt(token["id_token"], nil, config) do
{:ok, jwt} -> {:ok, jwt.claims}
{:error, error} -> {:error, error}
end
end
end
[
client_id: "redacted guid",
authorization_params: [
response_type: "id_token code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: MyApp.ADFS
]
And if you want to use OAuth2 strategy:
defmodule MyApp.ADFS do
use Assent.Strategy.OAuth2.Base
@impl true
def default_config(config) do
[
site: "https://login.redacted.com/adfs",
authorize_url: "/oauth2/authorize",
token_url: "/oauth2/token",
authorization_params: [
response_type: "code",
response_mode: "form_post"
]
]
end
@impl true
def normalize(_config, user), do: {:ok, user}
@impl true
def get_user(_config, _token), do: {:ok, %{}}
# Or if the access token has the claims:
#
# @impl true
# def get_user(config, token) do
# case Helpers.verify_jwt(token["access_token"], nil, config) do
# {:ok, jwt} -> {:ok, jwt.claims}
# {:error, error} -> {:error, error}
# end
# end
end
[
client_id: "redacted guid",
authorization_params: [
response_type: "code",
resource: "redacted guid",
response_mode: "form_post"
],
strategy: MyApp.ADFS
]
from assent.
Oh, btw using PowAssent it's expected that a sub
is returned, so the second example you should definitely use the commented get_user/2
method so you can at least get the id for the user.
from assent.
v0.1.5
released with #24 🚀
from assent.
Related Issues (20)
- Auth0: Support Variable-Length Access Token and Authorization Codes HOT 1
- PCKE support? HOT 2
- Multiple audiences HOT 5
- Allow to pass `state` parameter HOT 1
- Sign in with Apple: Strategy failed with error: :enoent HOT 1
- AssentJWT adapter returns unexpected value HOT 1
- Boolean field may contain an error-tuple which can cause issues HOT 1
- multiprovider: undefined variable config HOT 1
- Bad Request - Invalid Header with Entra ID (Azure AD) and Finch HOT 4
- support code_verifier/code_challenge in OAuth2
- Should OIDC fetch_user, fetch_userinfo, and validate_id_token allow for dynamic OpenID configuration? HOT 3
- OTP 24 :crypto.hmac/3 doesn't exist anymore HOT 2
- How to get the authorization code on react native for the Facebook strategy
- Callback param "user" is not parsed when using Apple strategy with "name" scope HOT 2
- Yandex OAuth Strategy
- Google Sign in for mobile strategy
- Using Tesla for HTTP HOT 1
- OIDC normalize/2 to conform to OAuth2 normalize/2 HOT 3
- Slack always "asks" for permission HOT 4
- Azure AD should expose more user info HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from assent.