In DjangoRestFramework you can change keyword in header for token authentification.
From docs
Note: If you want to use a different keyword in the header, such as
Bearer, simply subclass TokenAuthentication and set the keyword class
variable.
What is the purpose of changing default keyword?
I've seen 'Bearer', 'Basic' and a few other variants, but just don't understand the purpose of doing so.
Can anyone explain?
I found how we need to pass the keyword to TokenAuthentication.
class BearerAuthentication(authentication.TokenAuthentication):
'''
Simple token based authentication using utvsapitoken.
Clients should authenticate by passing the token key in the 'Authorization'
HTTP header, prepended with the string 'Bearer '. For example:
Authorization: Bearer 956e252a-513c-48c5-92dd-bfddc364e812
'''
keyword = 'Bearer'
Then instead of using authentication.TokenAuthentication in the settings.py we will use BearerAuthentication
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'your.models.BearerAuthentication',
)
}
Many web servers support multiple methods of authorization. In those
cases sending just the token isn't sufficient.
Source
Related
I have a Java/Spring-based microservices architecture with two services:
A - has a public-facing endpoint which does some stuff and then calls the below endpoint on B. This endpoint requires an Authorization header (OAuth2) to identify the user.
B - has an endpoint that also requires an Authorization header (OAuth2) so that it can determine which user made the call.
I have specified B's endpoint using OpenAPI. I'm using OpenAPI Generator to generate both the client in A (Spring WebClient), and the server in B (Spring Boot).
My question is this: what do I need to do to pass the Authorization header along from A to B? I see how to set a static header, but I don't know how to pass the header based on what's received by A.
Similar to this question, but for WebClient: OpenAPI client generator Java - header per call
As your A service is a resource-server and you want to issue request to service B on behalf of the user who initiated the request to A, just set a Bearer Authorization header on WebClient with the original access-token string retrieved from current security context (use SecurityContextHolder static accessor or have AbstractOAuth2TokenAuthenticationToken<?> auth auto-magically injected by Spring as #Controller method parameter).
If your A service was a client, you could do as I did in the UiController of this tutorial.
Turns out my problem was how I specified the endpoint security in my OpenAPI specification.
I added:
components:
securitySchemes:
s2s:
type: oauth2
flows:
clientCredentials:
authorizationUrl: https://example.com/oauth/authorize
tokenUrl: https://example.com/oauth/token
scopes:
read: Read scope
And made a reference to that security schema on my endpoint:
/foo:
get:
...
security:
- s2s:
- read
Now, when I run openapi-generate on this schema and generate it to either Spring Boot (server) or Java WebClient (client), the generated endpoint signature looks like:
#RequestMapping(
method = RequestMethod.GET,
value = "/foo",
produces = { "application/json" }
)
Mono<ResponseEntity<MyResponse>> foo(
#Parameter(name = "Authorization", description = "", required = true) #RequestHeader(value = "Authorization", required = true) String authorization,
#Parameter(hidden = true) final ServerWebExchange exchange
);
The String authorization argument to the method was not previously being generated and it's what I needed here. It allows me to pass A's header along to the call to B.
Props to #Ch4mp for helping out here.
I'm using springfox-swagger 3.0.0 to generate the Swagger UI (so I don't have much control over the Swagger UI code), and for my oauth2 authorization I've defined an application flow.
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_APPLICATION;
token_url: "/oauth2/token";
scopes: {
scope: {
key: "api"
value: "Grants access to api"
}
}
}
}
Now my problem is that the client ids my system uses, contains colon ":" characters, which are also use to separate client id from client secret in the authorization header. This messed up the logic at the token endpoint.
authorization: Basic YXBpOjk1NmZkYmEzLWE1ZmEtNDk0MS1iZDAzLWY3NGY0ZmNhYjM1ZjpzWFNXVlBpcklSN1dsUkRvOG9lNFM2VTR3OEI0VFg4VUUwNm9QR2FyWmVn
If I URL encode my client id value before passing it to the client_id field in the swagger console, everything works ok.
authorization: Basic YXBpJTNBOTU2ZmRiYTMtYTVmYS00OTQxLWJkMDMtZjc0ZjRmY2FiMzVmOnNYU1dWUGlySVI3V2xSRG84b2U0UzZVNHc4QjRUWDhVRTA2b1BHYXJaZWc=
Any idea how can I instruct swagger to URL encode the client id field value before packaging it in the header?
Thanks
You'll have to fork Swagger UI and implement the necessary change in your fork. Then, since you're using Springfox, you'll need to point it to your custom Swagger UI fork instead of the bundled version.
The code that constructs the Authorization header for OAuth requests lives here:
https://github.com/swagger-api/swagger-ui/blob/master/src/core/plugins/auth/actions.js
Tweak either the authorizePassword or authorizeApplication function (depending on your grant type) to percent-encode the clientId:
Authorization: "Basic " + btoa(encodeURIComponent(clientId) + ":" + clientSecret)
I try to use Google Photos API to upload my images, base on the steps of the following link.
https://developers.google.com/photos/library/guides/upload-media
After following the Using OAuth 2.0 for Web Server Applications, I just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...). However, after I put this token string with "Bearer " into request headers, the response is error 401, the error message is "code 16 Authentication session is not defined".
I cannot find any information to deal with it, thank for any help.
You probably have incorrect permissions. Make sure you request the token with the appropriate scope. For write-only access you need 'https://www.googleapis.com/auth/photoslibrary.appendonly'
src: https://developers.google.com/photos/library/guides/authentication-authorization#what-scopes
One reason this might be happening is that you initially authorized your user for read-only access. If you went through the authorization flow with a .readonly scope, your bearer token reflects that authorization (and the token is retained in your credentials file). If you change your scope but don't get a new auth token you will get this error when trying to upload. Simply redo the authorization flow with the new scope defined:
SCOPES = 'https://www.googleapis.com/auth/photoslibrary'
store = file.Storage('path_to_store')
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('google_credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
and your store will be populated with a new token that can be used for uploading.
You say you "just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...)" and "put this token string with "Bearer " into request headers".
Unfortunately documentation on this isn't super clear in a lot of places. What you are supposed to provide after "Bearer" is the "access_token" field only, not the entire JSON string with all the token fields in it. For reference, this is a single string of random looking characters which probably starts with "ya29." and is pretty long - in my case it's 170 characters.
I have a spring backend which i'm accessing my Elastic search cluster through by a proxylike endpoint. The request has to be authorized with a cookie.
I'm currently using searchkit with supports authenticating requests through the withCredentials flag. Is there a similar option for reactivesearch or is there any other solution for authorizing the request with a cookie?
I could add: the backend exposes a swagger client which runs on a different domain than my frontend client. This client "owns" the cookie and thus i cannot read the cookie from my frontend client
You can use the headers prop in ReactiveBase to pass custom headers along with the requests. Link to docs. Since there is no withCredentials you could read the cookies and set in custom headers to verify the requests at the proxy middleware.
<ReactiveBase
...
headers={{
customheader: 'abcxyz'
}}
>
<Component1 .. />
<Component2 .. />
</ReactiveBase>
Here is a sample proxy server but its in NodeJS
Okey so it turns out, Reactivesearch uses fetch and fetch wants credentials: 'include' for cookie authentication. This may not be placed in the headers that Reactivesearch supplies and must be placed on the root object for the request.
It's possible to do this by implementing beforeSend on ReactiveBase.
const Base = ({ children }) => {
const onBeforeSend = props => {
return {
...props,
credentials: 'include',
}
}
return (
<ReactiveBase
app="app-name"
url="url"
beforeSend={onBeforeSend}
>
{children}
</ReactiveBase>
)
}
I've a problem when trying to do a webrequest to UGC and authenticate using oAuth. I'm making a webrequest such as:-
WebRequest wr = WebRequest.Create("http://ugc.service/odata.svc/Ratings(Id=200)");
wr.Headers["authorization"] = "OAuth " + auth;
Where auth is my token returned from the access_token.svc. According to the documentation the token returned from the service should be something like:-
HufXeuUt%2FYYElA8SYjJOkUkrXxV9dyXRirmKhjW%2Fb%2FU%3D
However, what I'm being returned from access_token.svc is more like:-
{"access_token":"client_id%3dtestuser%26expiresOn%3d1361898714646%26digest%3d%2fW%2fvyhQneZHrm1aGhwOlgLtA9xGWd77hkxWbjmindtM%3d","expires_in":300}
I've parsed the JSON to extract various strings and attempted to pass these through to the authorization but whatever I try I get an error in the logs - "ERROR OAuth2AccessToken - Digest is wrong." Exactly what part of the token and in what format should I be passing through to authorization?
Many thanks
John
Like you mentioned, the protocol is this:
You make a post request to the access token end-point to get a token (you need to provide here your client_id and your client_secret as headers or as query parameters);
You get an answer similar to this: {"access_token":"sometoken","expires_in":300};
2.1 Worth knowing is that the token is url encoded and in UTF-8 format so, on Java side you need to do URLDecoder.decode("sometoken", "UTF-8"); while on .NET side you need to do HttpUtility.UrlDecode("sometoken", System.Text.Encoding.UTF8);;
Your next request needs to include the authorization header. On Java side you do builder.header("authorization", "OAuth " + decodedTokenString); while on .NET side you can use Client.Headers["authorization"] = "OAuth " + DecodedTokenString;
Worth mentioning is that the SharedSecret defined in the cd_webservice_conf.xml (/Configuration/AuthenticationServer/SharedSecret/) of the TokenAccessPoint needs to be the same as the SharedSecret defined in the cd_ambient_conf.xml (/Configuration/Security/SharedSecret/) of the (WebService)EndPoint.
Are you sure you decoded properly the token gotten from the server? Are you sure that you configured the proper SharedSecret in the two configuration files?
Hope this helps.