Authorization based on custom Header (Apache)What is the difference between authentication and authorization?Apache 2.4 RequestHeader while reverse proxying with ProxyPassUse of ProxyPassReverse to change Location response headerWhat is the use of ProxyPassReverse Directivemod_rewrite to serve static file based on specific query string with mod_proxyApache mod_proxy: redirection based on http header?Gitlab HTTPS URI for repository cloning does not work - SSL host could not be verified - fatal: unable to accessApache 2.4.7 mod_proxy_wstunnel tunneling too much (HTTP as well as WS)Migrate Apache Authorization Header rule to LighttpdApache Custom Header with an environment variable
What was the first story to feature the plot "the monsters were human all along"?
Why aren't nationalizations in Russia described as socialist?
Can a Valor bard Ready a bard spell, then use the Battle Magic feature to make a weapon attack before releasing the spell?
Should homeowners insurance cover the cost of the home?
How should I tell my manager I'm not paying for an optional after work event I'm not going to?
What are the advantages of luxury car brands like Acura/Lexus over their sibling non-luxury brands Honda/Toyota?
Adjacent DEM color matching in QGIS
Does it make sense for a function to return an rvalue reference?
Has the Hulk always been able to talk?
Saying “that” like “It’s nice that...” or “It makes me sad that...”
How long would it take for people to notice a mass disappearance?
Point of the Dothraki's attack in GoT S8E3?
Are the Night's Watch still required?
3D Volume in TIKZ
Pressure inside an infinite ocean?
Word for Food that's Gone 'Bad', but is Still Edible?
How do inspiraling black holes get closer?
What does 'made on' mean here?
Adding command shortcuts to bin
Copy previous line to current line from text file
Is “snitty” a popular American English term? What is its origin?
Can my company stop me from working overtime?
How can internet speed be 10 times slower without a router than when using a router?
Where is the documentation for this ex command?
Authorization based on custom Header (Apache)
What is the difference between authentication and authorization?Apache 2.4 RequestHeader while reverse proxying with ProxyPassUse of ProxyPassReverse to change Location response headerWhat is the use of ProxyPassReverse Directivemod_rewrite to serve static file based on specific query string with mod_proxyApache mod_proxy: redirection based on http header?Gitlab HTTPS URI for repository cloning does not work - SSL host could not be verified - fatal: unable to accessApache 2.4.7 mod_proxy_wstunnel tunneling too much (HTTP as well as WS)Migrate Apache Authorization Header rule to LighttpdApache Custom Header with an environment variable
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have a service running behind a Apache Reverse-Proxy that uses the custom headers "username" and "role" to identify users and their role.
I want Apache HTTPD to restrict access to to people whose custom HTTP-header "groupmembership" contains one of the following: "viewer","publisher","administrator".
The Apache sits behind another proxy which authenticates users and populates the HTTP Headers "username" and "groupmembership" where the contents of "groupmembership" is a comma-separated list with groups.
For reference I have included a draft of the architecture.
http-proxy-auth
How would this be possible? I have tried using a require directive like Require expr %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator'
inside <Location />
to no avail.
Could this instead work with mod_rewrite?
Here is the reverse-proxy config using mod_proxy and mod_rewrite:
RewriteEngine on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
ProxyPass / http://172.17.0.1:3939/
ProxyPassReverse / http://172.17.0.1:3939/
Thanks for any hints.
Edit: Basically, the question boils down to: How can I check if the comma-separated list in the groupmembership
Header contains either 'Administrator', 'Publisher' or 'Viewer'
apache-2.4 mod-rewrite mod-proxy http-headers authorization
add a comment |
I have a service running behind a Apache Reverse-Proxy that uses the custom headers "username" and "role" to identify users and their role.
I want Apache HTTPD to restrict access to to people whose custom HTTP-header "groupmembership" contains one of the following: "viewer","publisher","administrator".
The Apache sits behind another proxy which authenticates users and populates the HTTP Headers "username" and "groupmembership" where the contents of "groupmembership" is a comma-separated list with groups.
For reference I have included a draft of the architecture.
http-proxy-auth
How would this be possible? I have tried using a require directive like Require expr %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator'
inside <Location />
to no avail.
Could this instead work with mod_rewrite?
Here is the reverse-proxy config using mod_proxy and mod_rewrite:
RewriteEngine on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
ProxyPass / http://172.17.0.1:3939/
ProxyPassReverse / http://172.17.0.1:3939/
Thanks for any hints.
Edit: Basically, the question boils down to: How can I check if the comma-separated list in the groupmembership
Header contains either 'Administrator', 'Publisher' or 'Viewer'
apache-2.4 mod-rewrite mod-proxy http-headers authorization
add a comment |
I have a service running behind a Apache Reverse-Proxy that uses the custom headers "username" and "role" to identify users and their role.
I want Apache HTTPD to restrict access to to people whose custom HTTP-header "groupmembership" contains one of the following: "viewer","publisher","administrator".
The Apache sits behind another proxy which authenticates users and populates the HTTP Headers "username" and "groupmembership" where the contents of "groupmembership" is a comma-separated list with groups.
For reference I have included a draft of the architecture.
http-proxy-auth
How would this be possible? I have tried using a require directive like Require expr %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator'
inside <Location />
to no avail.
Could this instead work with mod_rewrite?
Here is the reverse-proxy config using mod_proxy and mod_rewrite:
RewriteEngine on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
ProxyPass / http://172.17.0.1:3939/
ProxyPassReverse / http://172.17.0.1:3939/
Thanks for any hints.
Edit: Basically, the question boils down to: How can I check if the comma-separated list in the groupmembership
Header contains either 'Administrator', 'Publisher' or 'Viewer'
apache-2.4 mod-rewrite mod-proxy http-headers authorization
I have a service running behind a Apache Reverse-Proxy that uses the custom headers "username" and "role" to identify users and their role.
I want Apache HTTPD to restrict access to to people whose custom HTTP-header "groupmembership" contains one of the following: "viewer","publisher","administrator".
The Apache sits behind another proxy which authenticates users and populates the HTTP Headers "username" and "groupmembership" where the contents of "groupmembership" is a comma-separated list with groups.
For reference I have included a draft of the architecture.
http-proxy-auth
How would this be possible? I have tried using a require directive like Require expr %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator'
inside <Location />
to no avail.
Could this instead work with mod_rewrite?
Here is the reverse-proxy config using mod_proxy and mod_rewrite:
RewriteEngine on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
ProxyPass / http://172.17.0.1:3939/
ProxyPassReverse / http://172.17.0.1:3939/
Thanks for any hints.
Edit: Basically, the question boils down to: How can I check if the comma-separated list in the groupmembership
Header contains either 'Administrator', 'Publisher' or 'Viewer'
apache-2.4 mod-rewrite mod-proxy http-headers authorization
apache-2.4 mod-rewrite mod-proxy http-headers authorization
edited Apr 25 at 7:17
juo
asked Apr 25 at 6:36
juojuo
184
184
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
This should do it. If you have a comma-separated list in header groupmembership
, then use the first regex expression. One value in the list has to match to grant access.
If you want to match an exact value in iv_groupmembership
, then uncomment the second third expression (and comment the first).
Edit:
- added
RequestHeader set role
example, uncomment as needed. I only tested this withHeader set role
(in the response, no backend), but should work withRequestHeader
the same way.
Edit2:
- removed
<Location/>
for clarity - added example for
X-Auth-Token
check combined withgroupmembership
Sample config:
# test for string in comma-separated values, one of the values must match
<If "%HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# combined: X-Auth-Token must be set or one of the roles must exist
# <If "%HTTP:X-Auth-Token == '' && %HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# alternative: test for a single value in "iv_groupmembership" (exact match)
# <If "! %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator' ">
Require all denied
</If>
# set role of groupmembership
# <If "%HTTP:groupmembership =~ /(^|,)viewer(,|$)/">
# RequestHeader set role viewer
# </If>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)publisher(,|$)/">
# RequestHeader set role publisher
# </ElseIf>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)administrator(,|$)/">
# RequestHeader set role administrator
# </ElseIf>
# set role of iv_groupmembership
# RequestHeader set role "expr=%HTTP:iv_groupmembership"
Modifying the headers in Apache (like RequestHeader set iv_groupmembership "viewer"
) to debug/test the config doesn't work,
you need to set the header very early.
https://httpd.apache.org/docs/2.4/expr.html#vars
The expression parser provides a number of variables of the form %HTTP_HOST. Note that the value of a variable may depend on the phase of the request processing in which it is evaluated. For example, an expression used in an <If > directive is evaluated before authentication is done. Therefore, %REMOTE_USER will not be set in this case.
You can test the configuration with wget from commandline, replace localhost
with your hostname.
# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost
# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost
Tested with Apache/2.4.25 (Debian)
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
add a comment |
Thanks @Freddy,
I got it working with the Require
and Expressions directives for the authorization part and putting the RequestHeader
directive inside <Virtualhost>
for setting the Role-Headers.
The final config looks like so:
<VirtualHost *:443>
ServerName ...
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/httpd/ssl/...
SSLCertificateKeyFile /etc/httpd/ssl/...
RewriteEngine on
#ProxyPreserveHost on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
# test for string in comma-separated values, one of the values must match
<If "%HTTP:iv_groupmembership !~ /(^|,)(Viewer|Publisher|Administrator)(,|$)/ && -z %HTTP:X-Auth-Token && %HTTP:Authorization !~ /Key .+/">
Require all denied
</If>
# set role of groupmembership
<If "%HTTP:iv_groupmembership =~ /(^|,)Viewer(,|$)/">
RequestHeader set Role viewer
</If>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Publisher(,|$)/">
RequestHeader set Role publisher
</ElseIf>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Administrator(,|$)/">
RequestHeader set Role administrator
</ElseIf>
</Virtualhost>
Thanks a lot!
Edit: how can I add additional logic in the Require
directive, so that if the header X-Auth-Token
is present, access is granted anyway?
Edit2: Thanks again @Freddy for the pointer to Apache expression-logic, I adapted the test for existence of the "X-Auth-Token" Header with -z %HTTP:X-Auth-Token
and could add another condition to pass through requests containing a key inside the "authorization" header.
See my Edit2, I also changed the syntax of the negated regex expr from! %.. =~
to%.. !~
, just so you know when you adapt the example.
– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "2"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f964521%2fauthorization-based-on-custom-header-apache%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This should do it. If you have a comma-separated list in header groupmembership
, then use the first regex expression. One value in the list has to match to grant access.
If you want to match an exact value in iv_groupmembership
, then uncomment the second third expression (and comment the first).
Edit:
- added
RequestHeader set role
example, uncomment as needed. I only tested this withHeader set role
(in the response, no backend), but should work withRequestHeader
the same way.
Edit2:
- removed
<Location/>
for clarity - added example for
X-Auth-Token
check combined withgroupmembership
Sample config:
# test for string in comma-separated values, one of the values must match
<If "%HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# combined: X-Auth-Token must be set or one of the roles must exist
# <If "%HTTP:X-Auth-Token == '' && %HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# alternative: test for a single value in "iv_groupmembership" (exact match)
# <If "! %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator' ">
Require all denied
</If>
# set role of groupmembership
# <If "%HTTP:groupmembership =~ /(^|,)viewer(,|$)/">
# RequestHeader set role viewer
# </If>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)publisher(,|$)/">
# RequestHeader set role publisher
# </ElseIf>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)administrator(,|$)/">
# RequestHeader set role administrator
# </ElseIf>
# set role of iv_groupmembership
# RequestHeader set role "expr=%HTTP:iv_groupmembership"
Modifying the headers in Apache (like RequestHeader set iv_groupmembership "viewer"
) to debug/test the config doesn't work,
you need to set the header very early.
https://httpd.apache.org/docs/2.4/expr.html#vars
The expression parser provides a number of variables of the form %HTTP_HOST. Note that the value of a variable may depend on the phase of the request processing in which it is evaluated. For example, an expression used in an <If > directive is evaluated before authentication is done. Therefore, %REMOTE_USER will not be set in this case.
You can test the configuration with wget from commandline, replace localhost
with your hostname.
# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost
# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost
Tested with Apache/2.4.25 (Debian)
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
add a comment |
This should do it. If you have a comma-separated list in header groupmembership
, then use the first regex expression. One value in the list has to match to grant access.
If you want to match an exact value in iv_groupmembership
, then uncomment the second third expression (and comment the first).
Edit:
- added
RequestHeader set role
example, uncomment as needed. I only tested this withHeader set role
(in the response, no backend), but should work withRequestHeader
the same way.
Edit2:
- removed
<Location/>
for clarity - added example for
X-Auth-Token
check combined withgroupmembership
Sample config:
# test for string in comma-separated values, one of the values must match
<If "%HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# combined: X-Auth-Token must be set or one of the roles must exist
# <If "%HTTP:X-Auth-Token == '' && %HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# alternative: test for a single value in "iv_groupmembership" (exact match)
# <If "! %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator' ">
Require all denied
</If>
# set role of groupmembership
# <If "%HTTP:groupmembership =~ /(^|,)viewer(,|$)/">
# RequestHeader set role viewer
# </If>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)publisher(,|$)/">
# RequestHeader set role publisher
# </ElseIf>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)administrator(,|$)/">
# RequestHeader set role administrator
# </ElseIf>
# set role of iv_groupmembership
# RequestHeader set role "expr=%HTTP:iv_groupmembership"
Modifying the headers in Apache (like RequestHeader set iv_groupmembership "viewer"
) to debug/test the config doesn't work,
you need to set the header very early.
https://httpd.apache.org/docs/2.4/expr.html#vars
The expression parser provides a number of variables of the form %HTTP_HOST. Note that the value of a variable may depend on the phase of the request processing in which it is evaluated. For example, an expression used in an <If > directive is evaluated before authentication is done. Therefore, %REMOTE_USER will not be set in this case.
You can test the configuration with wget from commandline, replace localhost
with your hostname.
# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost
# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost
Tested with Apache/2.4.25 (Debian)
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
add a comment |
This should do it. If you have a comma-separated list in header groupmembership
, then use the first regex expression. One value in the list has to match to grant access.
If you want to match an exact value in iv_groupmembership
, then uncomment the second third expression (and comment the first).
Edit:
- added
RequestHeader set role
example, uncomment as needed. I only tested this withHeader set role
(in the response, no backend), but should work withRequestHeader
the same way.
Edit2:
- removed
<Location/>
for clarity - added example for
X-Auth-Token
check combined withgroupmembership
Sample config:
# test for string in comma-separated values, one of the values must match
<If "%HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# combined: X-Auth-Token must be set or one of the roles must exist
# <If "%HTTP:X-Auth-Token == '' && %HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# alternative: test for a single value in "iv_groupmembership" (exact match)
# <If "! %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator' ">
Require all denied
</If>
# set role of groupmembership
# <If "%HTTP:groupmembership =~ /(^|,)viewer(,|$)/">
# RequestHeader set role viewer
# </If>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)publisher(,|$)/">
# RequestHeader set role publisher
# </ElseIf>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)administrator(,|$)/">
# RequestHeader set role administrator
# </ElseIf>
# set role of iv_groupmembership
# RequestHeader set role "expr=%HTTP:iv_groupmembership"
Modifying the headers in Apache (like RequestHeader set iv_groupmembership "viewer"
) to debug/test the config doesn't work,
you need to set the header very early.
https://httpd.apache.org/docs/2.4/expr.html#vars
The expression parser provides a number of variables of the form %HTTP_HOST. Note that the value of a variable may depend on the phase of the request processing in which it is evaluated. For example, an expression used in an <If > directive is evaluated before authentication is done. Therefore, %REMOTE_USER will not be set in this case.
You can test the configuration with wget from commandline, replace localhost
with your hostname.
# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost
# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost
Tested with Apache/2.4.25 (Debian)
This should do it. If you have a comma-separated list in header groupmembership
, then use the first regex expression. One value in the list has to match to grant access.
If you want to match an exact value in iv_groupmembership
, then uncomment the second third expression (and comment the first).
Edit:
- added
RequestHeader set role
example, uncomment as needed. I only tested this withHeader set role
(in the response, no backend), but should work withRequestHeader
the same way.
Edit2:
- removed
<Location/>
for clarity - added example for
X-Auth-Token
check combined withgroupmembership
Sample config:
# test for string in comma-separated values, one of the values must match
<If "%HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# combined: X-Auth-Token must be set or one of the roles must exist
# <If "%HTTP:X-Auth-Token == '' && %HTTP:groupmembership !~ /(^|,)(viewer|publisher|administrator)(,|$)/">
# alternative: test for a single value in "iv_groupmembership" (exact match)
# <If "! %HTTP:iv_groupmembership in 'viewer', 'publisher', 'administrator' ">
Require all denied
</If>
# set role of groupmembership
# <If "%HTTP:groupmembership =~ /(^|,)viewer(,|$)/">
# RequestHeader set role viewer
# </If>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)publisher(,|$)/">
# RequestHeader set role publisher
# </ElseIf>
# <ElseIf "%HTTP:groupmembership =~ /(^|,)administrator(,|$)/">
# RequestHeader set role administrator
# </ElseIf>
# set role of iv_groupmembership
# RequestHeader set role "expr=%HTTP:iv_groupmembership"
Modifying the headers in Apache (like RequestHeader set iv_groupmembership "viewer"
) to debug/test the config doesn't work,
you need to set the header very early.
https://httpd.apache.org/docs/2.4/expr.html#vars
The expression parser provides a number of variables of the form %HTTP_HOST. Note that the value of a variable may depend on the phase of the request processing in which it is evaluated. For example, an expression used in an <If > directive is evaluated before authentication is done. Therefore, %REMOTE_USER will not be set in this case.
You can test the configuration with wget from commandline, replace localhost
with your hostname.
# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost
# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost
Tested with Apache/2.4.25 (Debian)
edited Apr 25 at 22:28
answered Apr 25 at 10:24
FreddyFreddy
94119
94119
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
add a comment |
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Thanks for the really helpful answer!
– juo
Apr 25 at 11:36
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
Now, I actually need both: authorized access and setting a header "role" based on an exact match.
– juo
Apr 25 at 11:38
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
There is one problem. The RewriteRule [P,L] lines will take precedence on the Location blocks.
– user188737
Apr 25 at 12:58
add a comment |
Thanks @Freddy,
I got it working with the Require
and Expressions directives for the authorization part and putting the RequestHeader
directive inside <Virtualhost>
for setting the Role-Headers.
The final config looks like so:
<VirtualHost *:443>
ServerName ...
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/httpd/ssl/...
SSLCertificateKeyFile /etc/httpd/ssl/...
RewriteEngine on
#ProxyPreserveHost on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
# test for string in comma-separated values, one of the values must match
<If "%HTTP:iv_groupmembership !~ /(^|,)(Viewer|Publisher|Administrator)(,|$)/ && -z %HTTP:X-Auth-Token && %HTTP:Authorization !~ /Key .+/">
Require all denied
</If>
# set role of groupmembership
<If "%HTTP:iv_groupmembership =~ /(^|,)Viewer(,|$)/">
RequestHeader set Role viewer
</If>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Publisher(,|$)/">
RequestHeader set Role publisher
</ElseIf>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Administrator(,|$)/">
RequestHeader set Role administrator
</ElseIf>
</Virtualhost>
Thanks a lot!
Edit: how can I add additional logic in the Require
directive, so that if the header X-Auth-Token
is present, access is granted anyway?
Edit2: Thanks again @Freddy for the pointer to Apache expression-logic, I adapted the test for existence of the "X-Auth-Token" Header with -z %HTTP:X-Auth-Token
and could add another condition to pass through requests containing a key inside the "authorization" header.
See my Edit2, I also changed the syntax of the negated regex expr from! %.. =~
to%.. !~
, just so you know when you adapt the example.
– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
add a comment |
Thanks @Freddy,
I got it working with the Require
and Expressions directives for the authorization part and putting the RequestHeader
directive inside <Virtualhost>
for setting the Role-Headers.
The final config looks like so:
<VirtualHost *:443>
ServerName ...
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/httpd/ssl/...
SSLCertificateKeyFile /etc/httpd/ssl/...
RewriteEngine on
#ProxyPreserveHost on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
# test for string in comma-separated values, one of the values must match
<If "%HTTP:iv_groupmembership !~ /(^|,)(Viewer|Publisher|Administrator)(,|$)/ && -z %HTTP:X-Auth-Token && %HTTP:Authorization !~ /Key .+/">
Require all denied
</If>
# set role of groupmembership
<If "%HTTP:iv_groupmembership =~ /(^|,)Viewer(,|$)/">
RequestHeader set Role viewer
</If>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Publisher(,|$)/">
RequestHeader set Role publisher
</ElseIf>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Administrator(,|$)/">
RequestHeader set Role administrator
</ElseIf>
</Virtualhost>
Thanks a lot!
Edit: how can I add additional logic in the Require
directive, so that if the header X-Auth-Token
is present, access is granted anyway?
Edit2: Thanks again @Freddy for the pointer to Apache expression-logic, I adapted the test for existence of the "X-Auth-Token" Header with -z %HTTP:X-Auth-Token
and could add another condition to pass through requests containing a key inside the "authorization" header.
See my Edit2, I also changed the syntax of the negated regex expr from! %.. =~
to%.. !~
, just so you know when you adapt the example.
– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
add a comment |
Thanks @Freddy,
I got it working with the Require
and Expressions directives for the authorization part and putting the RequestHeader
directive inside <Virtualhost>
for setting the Role-Headers.
The final config looks like so:
<VirtualHost *:443>
ServerName ...
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/httpd/ssl/...
SSLCertificateKeyFile /etc/httpd/ssl/...
RewriteEngine on
#ProxyPreserveHost on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
# test for string in comma-separated values, one of the values must match
<If "%HTTP:iv_groupmembership !~ /(^|,)(Viewer|Publisher|Administrator)(,|$)/ && -z %HTTP:X-Auth-Token && %HTTP:Authorization !~ /Key .+/">
Require all denied
</If>
# set role of groupmembership
<If "%HTTP:iv_groupmembership =~ /(^|,)Viewer(,|$)/">
RequestHeader set Role viewer
</If>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Publisher(,|$)/">
RequestHeader set Role publisher
</ElseIf>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Administrator(,|$)/">
RequestHeader set Role administrator
</ElseIf>
</Virtualhost>
Thanks a lot!
Edit: how can I add additional logic in the Require
directive, so that if the header X-Auth-Token
is present, access is granted anyway?
Edit2: Thanks again @Freddy for the pointer to Apache expression-logic, I adapted the test for existence of the "X-Auth-Token" Header with -z %HTTP:X-Auth-Token
and could add another condition to pass through requests containing a key inside the "authorization" header.
Thanks @Freddy,
I got it working with the Require
and Expressions directives for the authorization part and putting the RequestHeader
directive inside <Virtualhost>
for setting the Role-Headers.
The final config looks like so:
<VirtualHost *:443>
ServerName ...
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/httpd/ssl/...
SSLCertificateKeyFile /etc/httpd/ssl/...
RewriteEngine on
#ProxyPreserveHost on
<Proxy *>
Allow from all
</Proxy>
ProxyRequests Off
# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%REQUEST_SCHEME]
RewriteRule . - [E=http_host:%HTTP_HOST]
RewriteRule . - [E=req_uri:%REQUEST_URI]
# set header with variables
RequestHeader set X-RSC-Request "%req_schemee://%http_hoste%req_urie"
RewriteCond %HTTP:Upgrade =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %HTTP:Upgrade !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
# test for string in comma-separated values, one of the values must match
<If "%HTTP:iv_groupmembership !~ /(^|,)(Viewer|Publisher|Administrator)(,|$)/ && -z %HTTP:X-Auth-Token && %HTTP:Authorization !~ /Key .+/">
Require all denied
</If>
# set role of groupmembership
<If "%HTTP:iv_groupmembership =~ /(^|,)Viewer(,|$)/">
RequestHeader set Role viewer
</If>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Publisher(,|$)/">
RequestHeader set Role publisher
</ElseIf>
<ElseIf "%HTTP:iv_groupmembership =~ /(^|,)Administrator(,|$)/">
RequestHeader set Role administrator
</ElseIf>
</Virtualhost>
Thanks a lot!
Edit: how can I add additional logic in the Require
directive, so that if the header X-Auth-Token
is present, access is granted anyway?
Edit2: Thanks again @Freddy for the pointer to Apache expression-logic, I adapted the test for existence of the "X-Auth-Token" Header with -z %HTTP:X-Auth-Token
and could add another condition to pass through requests containing a key inside the "authorization" header.
edited Apr 26 at 8:43
answered Apr 25 at 20:49
juojuo
184
184
See my Edit2, I also changed the syntax of the negated regex expr from! %.. =~
to%.. !~
, just so you know when you adapt the example.
– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
add a comment |
See my Edit2, I also changed the syntax of the negated regex expr from! %.. =~
to%.. !~
, just so you know when you adapt the example.
– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
See my Edit2, I also changed the syntax of the negated regex expr from
! %.. =~
to %.. !~
, just so you know when you adapt the example.– Freddy
Apr 25 at 22:21
See my Edit2, I also changed the syntax of the negated regex expr from
! %.. =~
to %.. !~
, just so you know when you adapt the example.– Freddy
Apr 25 at 22:21
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
Thanks @Freddy, it's working as expected, now =)
– juo
Apr 26 at 8:37
add a comment |
Thanks for contributing an answer to Server Fault!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f964521%2fauthorization-based-on-custom-header-apache%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown