how to route from one api to other fastapi - fastapi

I am trying to redirect request from protected_api() to login() function in fastapi. but it fails with messages
Failed to fetch.
Possible Reasons:
CORS
Network Failure
URL scheme must be "http" or "https" for CORS request.
what could be the issue and how can be redirect from one api to other
#app.get("/protected_api")
async def protected_api():
resp = RedirectResponse("https://localhost:5000/token")
return resp
#app.post("/token", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()): # login function to get access token
print('In login fun value of form_data dict.....%s' % form_data.__dict__)
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(seconds=ACCESS_TOKEN_EXPIRE_SECONDS)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
print('Value of access_token in login fun ......%s\n' % access_token)
return {"access_token": access_token, "token_type": "bearer"}

You're having clients ping A (/protected_api) but sending a response from B (/token). They are not the same endpoint, so this involves CORS. Try using CORSMiddleware with FastAPI to resolve this issue.

Related

How do I use the Azure AD Authorization Code Flow?

I am building an ASP.NET (v4.8) Web application that will be hosted as an Azure App Service, but for now we are on localhost.
I am configured for Azure AD successfully and I am receiving an authorization code because I configured my app service to send the access token. The app registration has ONLY User.Read (delegated) permissions.
In my Startup.cs file, I've configured OpenIdConnectAuthenticationNotifications so that I am receiving the access code in AuthorizationCodeReceived. Here is the code:
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType( CookieAuthenticationDefaults.AuthenticationType );
app.UseCookieAuthentication(new CookieAuthenticationOptions());
authority = aadInstance + tenantId;
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions {
ClientId = clientId, Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
TokenResponseReceived = (tr) => { return Task.FromResult(0); },
AuthorizationCodeReceived = (code) => {
// you are here! what's next?
access_code = code.Code;
return Task.FromResult(0);
},
SecurityTokenReceived = (token) =>
{
return Task.FromResult(0);
},
AuthenticationFailed = (context) => { return System.Threading.Tasks.Task.FromResult(0); }
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
My objective is to call this graph endpoint as the current user to get their JobTitle and > Department from Azure AD. Here is the resource: https://graph.microsoft.com/v1.0/me
I was following this documentation, but it was not clear what to do with the provided access_code. Please help me understand.
Is this access_code a bearer token? can I use it directly to call the graph API?
Do I have to use it to call the /token endpoint to get a bearer token?
Do I have to use it to call the /authorize endpoint to get a bearer token?
I am making direct HTTP requests now, should I use MSAL or Graph SDK?
I think I am trying to accomplish this step:
This is the code I am currently working on, and it returns HTTP CODE 400 (Bad Request):
private void GetOtherProfileData()
{
var cId = Startup.clientId;
var tenantId = Startup.tenantId;
var scope = Startup.scope;
// scope: https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
var code = Startup.access_code;
var redir = HttpUtility.UrlEncode(Startup.redirectUri);
var req_url = $#"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token?client_id={cId}&scope={scope}
&code={code}&redirect_uri={redir}&grant_type=authorization_code
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong";
var req = WebRequest.CreateHttp(req_url);
req.Method = "POST";
req.ContentLength = 0;
req.ContentType = "application/x-www-form-urlencoded";
var resp = req.GetResponse();
var str = resp.GetResponseStream();
var json = new StreamReader(str).ReadToEnd();
Trace.TraceInformation(json);
/// this should return bearer token and then we go call the /me endpoint...
///right?
}
Any code samples or pointers to recent documentation would be helpful.
Is this access_code a bearer token? can I use it directly to call the graph API?
No, code and Access_token are different. You will need a access_token to call Graph API.
Do I have to use it to call the /token endpoint to get a bearer token?
Yes, you'll need code to call token endpoint to get the bearer token.
Do I have to use it to call the /authorize endpoint to get a bearer token?
You will get the code after calling authorize endpoint. You need to pass grant_type=code to get the code in response.
I am making direct HTTP requests now, should I use MSAL or Graph SDK?
You'll need to call Graph API after you get the access_token. Along with the token it also needs proper dedicated and application User permissions from Azure side.
I found a good sample here: https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect
I was trying to do this without a client secret, that was a mistake.
This is how I implemented it =>
AuthorizationCodeReceived = async (context) => {
// you are here!
IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "User.Read" }, context.Code)
.WithSpaAuthorizationCode() //Request an authcode for the front end
.ExecuteAsync();
access_code = result.AccessToken;
// this is the bearer token.
},
This is what is inside the implementation of BuildConfidentialClientApplication:
clientapp = ConfidentialClientApplicationBuilder.Create(Startup.clientId)
.WithClientSecret(Startup.secret)
.WithRedirectUri(Startup.redirectUri)
.WithAuthority(new Uri(Startup.authority))
.Build();

get_current_user doesn't work (OAuth2PasswordBearer problems)

This is actually the first time it doesn't work, I mean I've practiced this before, but now I have no idea what's wrong.
So I am trying to implement basic function get_current_user for FastAPI , but somehow it doesn't work.
When I try in swagger Authorization works fine, but endpoint with current user simply doesn't work.
So this is part that belongs to endpoint file:
router = APIRouter(prefix='/api/v1/users')
router1 = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl='/api-token-auth/')
#router1.post('/api-token-auth/')
async def auth(form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
user = await utils.get_user_by_username(form.username, db) # type: User
if not user:
raise HTTPException(status_code=400, detail="Incorrect username or password")
if not utils.validate_password(form.password, user.hashed_password):
raise HTTPException(status_code=400, detail="Incorrect username or password")
return await utils.create_token(user.id, db)
async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
print(token)
user = await utils.get_user_by_token(token, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return user
#router.get("/me", response_model=DisplayUser)
async def read_users_me(current_user: User = Depends(get_current_user)):
return current_user
and this is function that creates token (I have checked and it is 1000% works and returns string):
async def create_token(user_id: int, db: Session):
"""Token generation"""
letters = string.ascii_lowercase
token = ''.join(random.choice(letters) for _ in range(25))
created_token = Token(
expires=datetime.now() + timedelta(weeks=2),
user_id=user_id,
token=token
)
db.add(created_token)
db.commit()
db.refresh(created_token)
token = AuthUser.from_orm(created_token)
return token.token
But when I print(token) in get_current_user function it prints undefined . And I dunno why. Am I using dependency wrong or something?
Thanks in advance!
Since it prints undefined it seems like the frontend is expecting the response in a different format (since undefined is what using an undefined object key in Javascript as a key will result in).
The OAuth2 response should have the token under access_token by default:
access_token (required) The access token string as issued by the authorization server.
token_type (required) The type of token this is, typically just the string “bearer”.
Example response from the above link:
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create"
}
In your "create_token(user.id, db)" ensure the returned token contains these two values.
{
"access_token":"",
"token_type":"bearer"
}

Firebase refresh id tokens for server authentication

I have a project using firebase where I use firebase id token to verify user on back-end.
Actually, on client, when a user login I use getIdToken(true) and attach it to my requests header.
On server for each request I use verifyIdToken to check if the user is logged in and it's valid.
The problem is that after some time the token expire and the backend is not able to verify the user.
My question is: how to get this work?
I think about using a request interceptor from client side to get an id token for each request but i don't know if this is a good practice and if I have to invalidate the other tokens too with admin.auth().revokeRefreshTokens(userId).
Thanks in advance.
client
axios.interceptors.request.use(function (config) {
if (!firebase.auth().currentUser) {
return config
}
return firebase.auth().currentUser.getIdToken(true).then(token => {
config.headers.Authentication = token
return config
})
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
server
let decodedToken = await admin.auth().verifyIdToken(token);
let userId = decodedToken.uid;

How to send Get and Post request with POCO Library and OAuth2

I have a native window app program,and want access API of gitlab service,hope to get token using name and password with using POCO Library and OAuth2,but I don't know how to send Get and Post request to gitlab with OAuth2,and using POCO Library, please give me a example.
Here is the data that needs to be sent and received.
Requesting access token
POST request to /oauth/token with parameters:
{
"grant_type" : "password",
"username" : "user#example.com",
"password" : "secret"
}
Then, you'll receive the access token back in the response:
{
"access_token": "1f0af717251950dbd4d73154fdf0a474a5c5119adad999683f5b450c460726aa",
"token_type": "bearer",
"expires_in": 7200
}
First you need to create a HTTPRequest object like so:
Poco::Net::HTTPClientSession* session = Poco::Net::HTTPSessionFactory::defaultFactory().createClientSession(serverUri);
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, serverUri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
Then create a HTMLForm:
Poco::Net::HTMLForm form;
form.add("grant_type", "password");
form.add("client_id", "client token");
form.add("client_secret", "client secret");
form.add("username", "user#example.com");
form.add("password", "secret");
form.prepareSubmit(request);
Send the request and write the form data into the output stream of the request:
std::ostream& requestStream = session->sendRequest(request);
form.write(requestStream);
Get the response out of the session:
Poco::Net::HTTPResponse response;
std::istream& responseStream = session->receiveResponse(response);
std::stringstream rawJson;
Poco::StreamCopier::copyStream(responseStream, rawJson);
Parse the raw JSON:
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr authObj = parser.parse(rawJson).extract<Poco::JSON::Object::Ptr>();
Create a new session for next request and attach an authorization header to the request:
Poco::Net::HTTPClientSession* dataSession = Poco::Net::HTTPSessionFactory::defaultFactory().createClientSession(dataUri);
Poco::Net::HTTPRequest dataRequest(Poco::Net::HTTPRequest::HTTP_GET, dataUri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
dataRequest.add("Authorization", "Bearer " + authObj->get("access_token"));
dataSession->sendRequest(dataRequest);
Get the response and read the data from stream:
std::stringstream data;
Poco::Net::HTTPResponse dataResponse;
Poco::StreamCopier::copyStream(dataSession->receiveResponse(dataResponse), data);
Hope it helps or points into the right direction.

node.js, passport-wordpress: The required "redirect_uri" parameter is missing

Trying to create a demo using passport-wordpress
https://www.npmjs.org/package/passport-wordpress
passport-wordpress allows you to login to a node.js app using your credentials at wordpress.com
I set up my Wordpress app at developer.wordpress.com/apps:
OAuth Information
Client ID <removed>
Client Secret <removed>
Redirect URL http://greendept.com/wp-pass/
Javascript Origins http://wp-node2.herokuapp.com
Type Web
Request token URL https://public-api.wordpress.com/oauth2/token
Authorize URL https://public-api.wordpress.com/oauth2/authorize
Authenticate URL https://public-api.wordpress.com/oauth2/authenticate
In my node.js app:
var CLIENT_ID = <removed>;
var CLIENT_SECRET = <removed>;
passport.use(new WordpressStrategy({
clientID: CLIENT_ID,
clientSecret: CLIENT_SECRET
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({ WordpressId: profile.id }, function (err, user) {
return done(err, user);
});
}
When I try to authorize, it goes to this URL (as one line, I've divided into two here for readability):
https://public-api.wordpress.com/oauth2/authorize?
response_type=code&redirect_uri=&client_id= removed
I can see that the redirect_uri is missing in that URL, so it's not surprising that I get this error:
Invalid request, please go back and try again.
Error Code: invalid_request
Error Message: The required "redirect_uri" parameter is missing.
Not sure where or how in my code I should be submitting the redirect_uri.
You need to pass a callback url as option.
From passport-wordpress
The strategy requires a verify callback, which accepts these credentials and
calls done providing a user, as well as options specifying a client ID,
client secret, and callback URL.
And from lib/strategy.js
Examples:
passport.use(new WordpressStrategy({
clientID: '123-456-789',
clientSecret: 'shhh-its-a-secret',
callbackURL: 'https://www.example.net/auth/wordpress/callback'
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate(..., function (err, user) {
done(err, user);
});
}
));

Resources