Redirect URLs in Microsoft application registration - microsoft-graph-api

In my Microsoft application registration, under "redirect URLs", I've checked Allow Implicit flow and provided the URL, http://localhost:8080/event.
But I actually have an dynamic event id which makes the URL localhost:8080/event/{eventid}.
So now I'm getting an error:
The reply address http://localhost:8080/student/event/59b67936d53f013a79000009 does not match the reply addresses configured for the application
How can I give a URL that will allow any value after the event in the URL?

You cannot use a dynamic URI for OAUTH redirects. Note that this isn't specific to Microsoft's v2 Endpoint, this is the case for every OAUTH provider I've used.
I assume you're looking to redirect the user to a specific event page after they've completed the login?
The proper way to handle that is to use the state parameter. This is a string value and will be returned with the response. For example, you could encode your eventid an include that value in the state. When you get the token response back, you're app decodes the state value and redirects the user.

Related

What is the point of PostLogoutRedirectUri in Open Id/OAuth2.0 logout?

I've been using Identity Server 4.0 as my OpenId Connect provider. I can setup clients in Identity Server with Redirect Uris and Post Logout Redirect Uris. I've also been using the angular-auth-oidc-client to login/logout via the Identity server.
When logging in, my client library (angular-auth-oidc-client) does pass in the correct Uri specified in the config when calling the authorize endpoint. When I try to login with an incorrect Redirect Uri, Identity Server checks and validates that the Uri provided by the client is one of the accepted one for that client, and shows an error if it isnt (as expected).
When it comes to logout, none of it seems to be built in. My client library does not send the PostLogoutRedirectUri when calling the logout endpoint. Identity Server's sample code for logout does not except any URIs to be passed in. It's sample code simply gets the Post Logout Redirect Uri value from the database and creates a link on the logged out page. Not only does the sample code not allow the user to specify the Redirect Uri for logout, but it doesn't do any checks or even do a redirect (granted its only sample code and I can change it). I would expect my client library to pass the Uri along and Identity Server to redirect to the Uri after successful logout as long as its one of the "approved" Uris for the client.
My question is: What even is the point of PostLogoutRedirectUri? Neither Identity Server nor the OIDC client library I'm using do anything useful with it. There doesn't even seem to be an agreed upon convention for the name of the query string parameters to use to pass this Uri to Identity Server. And yet, both the Identity Server and the angular client library seem to have some support for it. So what's the point of this thing? Is it something that will be added or fleshed out later? Did I miss some documentation describing what its for and how to use it?
It's a draft standard and support differs between libraries and vendors, but here is a summary:
A client uses the post logout redirect URI to log out in a controlled way, typically redirecting to an application page that gives the user a link to sign in again
A client could potentially have more than one post_logout_redirect_uri and decide which to use based on runtime conditions
The post_logout_redirect_uri sent is meant to only be honoured if it is accompanied by an id_token_hint - and if it matches a configured value against the OAuth client. I believe OIDC will send the current id token but it is worth checking that this is happening in your browser tools.
If a post_logout_redirect_uri is not sent then the Authorization Server may use the default one configured
See the official IETF docs on how this is meant to work.
In my own application, I set it to the /Signout-callback-oidc URL of the client, like
PostLogoutRedirectUris = { "https://localhost:5001/signout-callback-oidc" },
The /signout-callback-oidc path is defined as in the source code here:
/// <summary>
/// The request path within the application's base path where the user agent will be returned after sign out from the identity provider.
/// See post_logout_redirect_uri from http://openid.net/specs/openid-connect-session-1_0.html#RedirectionAfterLogout.
/// </summary>
public PathString SignedOutCallbackPath { get; set; }
I hope this can give some clarification.
There are two sessions, one in the UI, and another on the server. It might need to call a URL on the backend to remove the user session on the server, otherwise the server won't know you are logged out on the UI.

OAuth2 with Hash query string, Imgur API

I'm updating my desktop app, an Imgur client, for the upcoming deprecation of code/pin auth methods, by using a local web server to catch the redirect_url from the browser after the user authorizes access to the app. So I launch the URL in the browser, the user accepts, then Imgur redirects to
http://localhost:7710/myapp?state=auth#access_token=....&expires_in=
etc
but the browser cuts the URL at # so all the variables are missing, and my app only receives "state=auth"
from Imgur's API docs:
The response_type Parameter token: This authorization flow will
directly return the access_token and refresh_token via the redirect
URL you specified during registration, in the form of hash query
string parameters. Example:
http://example.com#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600
The code and pin response types have been deprecated and will soon no
longer be supported.
Imgur returns an access token to your application if the user grants
your application the permissions it requested. The access token is
returned to your application in the fragment as part of the
access_token parameter. Since a fragment (the part of the URL after
the #) is not sent to the server, client side javascript must parse
the fragment and extract the value of the access_token parameter.
Clearly they haven't thought this through for desktop applications, or am I missing something?
Imgur stuff looks non standard, since response_type=token is a basic version of the implicit flow, which used to be the solution for single page pps.
These days all UI based flows should use Authorization Code Flow (PKCE) and response_type=code.
Since your app is acting as a (loopback) web server it will not receive the hash fragment parameters, which are only available to JavaScript code running in a browser.
One option that would enable you to get the full URL would be to login via the system browser and to use a Private URI Scheme to call back to the app.
The above link is a visual blog post to explain how this works, in case it is of interest.

Microsoft Graph API redirect_uri doesn't allow query strings

We're trying to move from the older WindowsLive API to the new Microsoft Graph API. In the process, we're running into difficulty with the required OAuth 2.0 redirect_uri parameter in the app.
According to the Oauth 2.0 RFC, the redirect_uri must be an absolute path but can contain a properly encoded query string.
In our Windows app, we've setup the absolute path - their application tool doesn't allow query strings to be added: https://example.com/index.php
The OAuth request we make uses a redirect_uri with URL Encoding, including query params. This is necessary, we use a CMS (Joomla) that needs to know what should handle the request:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
response_type=code&
client_id={string}&
redirect_uri=https%3A%2F%2Fexample.com%2Findex.php%3Foption%3Dcom_jfbconnect%26task%3Dauthenticate.callback%26provider%3Dwindowslive&
scope=user.read&
state={string}&
access_type=offline&
approval_prompt=auto
However, the Graph API rejects this with:
"The reply url specified in the request does not match the reply urls configured for the application"
Anyone else run into this or understand why the Graph API doesn't accept query parameters either in the app configuration or on the token requests?
Edit - 5/8 - However, the application setup area does not allow query strings in the redirect_uri setting, which is correct according to the RFC. However, the Graph API isn't respecting this note of the RFC:
The endpoint URI MAY include an "application/x-www-form-urlencoded" formatted (per Appendix B) query component ([RFC3986] Section 3.4), which MUST be retained when adding additional query parameters.
This isn't actually being rejected by Microsoft Graph. Microsoft Graph is simply an API and it doesn't generate or manage access tokens. That process is handled by Azure Active Directory.
The error you're getting is due to your redirect_uri not being configured in your app registration at https://apps.dev.microsoft.com. The URL must explicitly match the URL configured in the registration. From the documentation:
The redirect_uri of your app, where authentication responses can be sent and received by your app. It must exactly match one of the redirect URIs you registered in the portal, except it must be url encoded.
For scenarios where you need to pass data through, you should encode those values in your state parameter. This will be returned to your redirect URI along with the authorization code.
Also note that neither access_type=offline or approval_prompt=auto are valid query parameters:
To retrieve a refresh_token, you add offline to your list of scopes (user.read+offline).
To set the type of prompt the user receives you use the prompt parameter. Valid options are login, none, and consent.

passing the state parameters through the OAuth flow

We have a multi-tenant application (AccountingSuite.com) and we want to have a Connect to Dwolla button in the application.
The button will open:
https://www.dwolla.com/oauth/v2/authenticate?client_id={client_id}&response_type=code&redirect_uri={redirect_uri}&scope={scope}&state={instance_id}
notice there is the state parameter at the end identifying an instance in our multi-tenant app. After a successful authentication the response URI needs to contain the state parameter, otherwise it's impossible for us to find out which instance sent a connect request. Currently the state parameter is stripped in the return.
This is a pretty standard OAuth flow (see, for example Stripe).
Please let me what I don't do right, or pass through the state parameter in the OAuth flow.
While Dwolla doesn't support a state parameter, as an alternative, you can specify the state parameter as a querystring variable in the return_uri.
For example, if you used this return URI:
http://www.example.com/somepage?state=foobar
After granting permissions to your application on Dwolla, the user will be redirected to your application via:
http://www.example.com/somepage?state=foobar&code={OAuth Verification Code}

DotNetOpenAuth OAuth2.0 state parameter

I'm using DotNetOpenAuth to connect to Facebook and Google via OAuth2. The OAuth specs ask that no additional parameters be supplied in the request_uri and Google actually enforces this somewhat by forcing to to specify an exact call back uri when you define your Google App with them.
What I want to accomplish is to be able to return the user to a specific URL after they have been authenticated with Facebook or Google. The flow is this, the user clicks on a protected link, they get forwarded to my login page with a returnUrl parameter and then I kick off the authorization process based on the OAuth2 authorization server they choose.
Since the request_uri can't have any parameters in it (though Facebook lets you get away with this), I can't send the returnUrl parameter to the authorization server and get it back such that when the user is returned to my site, I forward them to the protected page they were trying to access. The best I can do is to forward them to the homepage or a member welcome page.
The way to fix this is to use the "state" parameter which the authorization server will send back to the request_uri, but I can't find a way to specify this with DotNetOpenAuth.
By default, it looks like the code uses the SessionID as the state parameter to verify the request coming back from the authorization server. Specifying an IClientAuthorizationTracker on the WebServerClient class lets me plug in my logic when the response is coming back from the authorization server but it's not called when the authorization request is being prepared, so I can't plug in my additional state.
This is code from WebServerClient.cs's PrepareRequestUserAuthorization:
// Mitigate XSRF attacks by including a state value that would be unpredictable between users, but
// verifiable for the same user/session.
// If the host is implementing the authorization tracker though, they're handling this protection themselves.
if (this.AuthorizationTracker == null) {
var context = this.Channel.GetHttpContext();
if (context.Session != null) {
request.ClientState = context.Session.SessionID;
} else {
Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be set to mitigate XSRF attacks.");
}
}
There is no else block here which is what I would have expected to be able to play along and plug in my own data.
Any tips on what I'm missing?
The state parameter is necessarily preoccupied with mitigating XSRF attacks. Since you already have a user session, can you just store the returnUrl in the session dictionary?
Alternatively, you can file an issue with DotNetOpenAuth asking that you be allowed to bundle your own data into the state parameter (along with DNOA's own XSRF mitigation code).

Resources