4

Our senior dev left us recently and i'm trying to swim into the ocean that is IdentityServer.

There is a few things I don't understand and can't find informations on it. Like for example, when you run the client application, it is redirrected to IdentityServer/Account/Login with a parameter called returnUrl.

That returnUrl seems to be used for many things, like retrieving the authorization context with :

await _interaction.GetAuthorizationContextAsync(returnUrl);

My first question would be :

From where is that returnUrl coming from? how/where is it created?

Second question is :

Is there a way to store it somewhere in the client application after you sign-in? I mean, there is a point in the client application where we have to send mails to create new accounts. Those mails redirrect new users in a "register" page in IdentityServer. What i'd like to do is to have the returnUrl here to redirrect the new user to the correct client application.

Thanks for your time !

EDIT :

here is the return url set in my Client (in IdentityServer) :

RedirectUris = {"http://localhost:44349" + "/signin-oidc"}

and here is the returnUrl recieve by the Login method in IdentityServer when i start the client application

"/connect/authorize/callback?client_id=MyApplication_Web&redirect_uri=http%3A%2F%2Flocalhost%3A44349%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20offline_access%20roles%20Cri_Identity_Serveur_Api.Full_Access&response_mode=form_post&nonce=637230882720491348.YmQzODA4ZTQtNDczZS00OWYwLWFmNmEtYjA2NmQ3YmIwZjg2YzdiODk4ZDYtMTU1YS00ZTM0LWE0MGEtNDVjOWNkZWFiYTM1&state=CfDJ8Ly2XCz96vdGkR4YQuJ4jeE-v9P4l1W7fLWpJcCGZpt1rMpXyWqEGdnaeRZfiZy4M4Z79LcixUbo06zImhsxwbgyV4hK82qmn0mI6wkrxwraT1tH3XNCdSXCfUJqwk_hZguMSwspZDEN6r1WxnZsU9kT8MHrb9qpzsMOMzsotVzToEjgMtxIeoRfqFSoK8ZfUXBkSw__qxVyIe1lCs96-I--ufZSyO2pBe2kfau-ah7eR5-9oopxX6x1k0tzFHAk6Y3_jMqGysES_GmmfeUJvXXFIR35Rc-IaxU1igswmL2h1IUS-0DQ98Tv_Gf3hirnS87SU87aSJhajgn2YmARXWc&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.3.0.0"

it seems that to retrieve the autorization context using await _interaction.GetAuthorizationContextAsync(returnUrl); the returnUrl must be the entire url with "/connect/authorize/callback?..."

j0w
  • 505
  • 2
  • 12
  • 32

2 Answers2

7

Unfortunatley Martin's answer is incorrect - returnUrl in this case is the authorize endpoint URL that was originally requested by the client. If the user is not authenticated then that endpoint will redirect to your nominated sign in UI endpoint and include this param. GetAuthorizationContextAsync() simply analyses that URL and if it's matches the signature of an authorize endpoint URL then it will parse, validate and return you an object representing that original request. You can then customise your sign in flow based on that info (e.g. show the name of the client you're signing into or restrict what social sign in methods are available or any number of other things).

You could include this URL in your sign up flow but personally I'd favour a single-use code based email verification flow and that means the user doesn't lose context if for example signing into a native mobile app and also doesn't need an email client on the device they're signing up on - e.g. a phone which doesn't have access to their work email account. Everyone's requirements are different though.

mackie
  • 4,996
  • 1
  • 17
  • 17
  • Thanks for the detailed answer. It helped understand that returnUrl thing better :) – j0w Apr 22 '20 at 16:19
  • I have a similar problem. I need to somehow push that returnUrl through the whole ResetPassword flow so that when they finally return to the login page, that returnUrl is set in the querystring of the login Action. Running into UrlEncoding issues, as the url is really a url within a url. If you've done something similar, I'd love to know how. Thanks. – onefootswill Oct 21 '22 at 22:33
1

From where is that returnUrl coming from? how/where is it created?

The return URL is specified as redirect_uri by the client who calls Identity Server. It is a callback address.

Clients are configured in Identity Server and for each configured client it is configured a list of allowed redirect URIs to return tokens or authorization codes to with RedirectUris property of the Client class. The configuration is in a class called Config which has method GetClients.

public class Config
{
    public static IEnumerable<Client> GetClients(IdentityServerAppSettings settings)
    {
        return new[]
        {
            new Client
            {
                ClientId = "roivenue-frontend",
                RedirectUris = new [] { "https://myappurl/somepage.html" }, // list of allowed URLs
                ...
            },

If the address sent by the client as redurect_uri does not match any of the configured addresses, the request validation fails in Identity Server.

Is there a way to store it somewhere in the client application after you sign-in?

The callback address is in the client application you are developing. It can be any address that is known to Identity Server with the configuration above.

Martin Staufcik
  • 8,295
  • 4
  • 44
  • 63
  • So, if i understand it correctly, if my `Client` is set like this ` RedirectUris = {"http://my-url-here" + "/signin-oidc"}, the `_interaction.GetAuthorizationContextAsync(returnUrl)` will only work if it recieve that same url, right? I just don't get how the callback address in client application is generated when calling IdentityServer ... – j0w Apr 21 '20 at 17:47
  • Yes, that is right. What is your client application, is it a javascript client or some other application? For a javascript client it is straightforward, changing location to the Authorize Endpoint - described [here](https://identityserver4.readthedocs.io/en/latest/endpoints/authorize.html). – Martin Staufcik Apr 21 '20 at 17:58
  • Just edited the original post to add the address that is configured in IdentityServer Client, and the address that is passed to the Login method when i run the client application. I can see that the address is stored in `redirect_uri=`, but does it mean that if i do `await _interaction.GetAuthorizationContextAsync("http://localhost:44349" + "/signin-oidc");` it will give me the right authorization context? – j0w Apr 21 '20 at 18:00
  • My client is an asp-net core mvc application – j0w Apr 21 '20 at 18:00
  • Yes, method `GetAuthorizationContextAsync` returns a valid context. – Martin Staufcik Apr 21 '20 at 18:08
  • Well, it seems `GetAuthorizationContextAsync("http://localhost:44349" + "/signin-oidc")`, in my case, returns `null` – j0w Apr 21 '20 at 18:09
  • 1
    The answer to [this post](https://stackoverflow.com/questions/42450840/user-registration-process-with-identityserver4) states that IdentityServer is for authenticating existing users, not really creating new users. In this solution, users are created by a call to the API, which creates the appropriate structures in the identity provider. – Martin Staufcik Apr 21 '20 at 18:43