Nginx server rewrite rule with Regex to add parameter in URL

Surya Prakash Pandey
3 min readApr 8, 2020
Photo by Frederic Köberl on Unsplash

After struggling for more than half a day to find a proper way for rewriting the rules for Nginx server. The major reason behind, there are very less clean information available for this. So I decided to write a post about it.

Although it seems very easy since it only requires three parameter to rewrite,

rewrite regex URL [flag];

But figuring out these three parameter is not the easy task. So after googling out few resources I have concluded to this post that I am going to write, I hope readers find it useful.

For starters we can start with this knowledge that there are good amount of variables are available for nginx config file. You can check the list here.

http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_

Few important variables that we are going to use here are $args, $args_name, $uri etc.

If you are interested in checking the value of variables that are coming to nginx config file, you can do that by using return directive.

return 200 “variable_name”;

Now coming back to rewrite directive,this is part of ngx_http_rewrite_module module. It is used to change request URI using PCRE regular expressions, return redirects, and conditionally select configurations.

So I have a scenario where I am using Keycloak for Identity Management with various authentication and authorization protocol like OpenID connect, SAML and Social IdP as well. I need user with specific URL to redirect directly to there specific provider.

For the above scenario Keycloak provides a facility by setting the kc_idp_hint query parameter in the Authorization Code Flow authorization endpoint.

For example:

GET /myapplication.com?kc_idp_hint=facebook HTTP/1.1

Now for this purpose I need to rewrite rule in nginx config file to add this kc_idp_hint parameter with appropriate provider name. Now let say I am getting URL as,

https://{KK}/realms/RealmName/protocol/openid-connect/auth?xxxxx&redirect_uri=https%3A%2F%2Fserver1%3A443%2Fapps%2Fkeycloak&yyyyy

That needs to be rewrite as,

https://{KK}/realms/RealmName/protocol/openid-connect/auth?xxxxx&redirect_uri=https%3A%2F%2Fserver1%3A443%2Foidapps%2Fkeycloak&yyyyy&kc_idp_hint=google

Let say for server1 it is google, for server2 it is Facebook and for server3 it is OIDC.

Now first thing I need to check the request coming from which server. For that I need to use if condition with regex to check the server1 string present in redirect_uri parameter,

if ($arg_redirect_uri ~ ^(https.*server1.*)){
// your rewrite rule will come here
}

Here arg_redirect_uri is nginx config variable. This expression will check from “server1” string present in redirect_uri.

Coming to rewrite rule expression, first we need to write regex to get the URL which we need to rewrite,

^(/auth/.*)/RealmName/(\w+\.?.*$)

Where “RealmName” is identifier for my URL and /auth is start point, you need to figure out that for yours. Parentheses helps here to group the URL part in variable which is default available to nginx config file. Now here these two parentheses are accessible using variable $1 and $2 respectively.

So the second part URL will be formed using these variables,

$1/RealmName/$2?kc_idp_hint=google

Here I have append the parameter that I needed to URL. By default nginx support QSA(query string append) feature as in Apache. So by default all the other parameters will be added to URL. We do not explicitly need to do anything for that.

Last thing we need to care about is flag, there are four flags available for this.

Last: stops processing the current set of directives and starts a search for a new location.
Break: Stops processing the current set of directives.If directive is specified inside the location, further processing of the request continues in this location.
Redirect: returns a temporary redirect with the 302 code
Permanent: returns a permanent redirect with the 301 code.

So here I am going to use “break” flag, since I need further processing of request in current location.

So here is my complete rewrite rule written inside if condition,

location /auth/{
if ($arg_redirect_uri ~ ^(https.*server1.*)){
rewrite ^(/auth/.*)/RealmName/(\w+\.?.*$) $1/RealmName/$2?kc_idp_hint=google break;
}
}

This is all for rewriting rule for nginx config from me. Let me know if this is helpful or I need to add some more details to it.

--

--

Surya Prakash Pandey

A problem solver, who sometimes blogs about how problem was solved.