Cognito throws ErrCodeNotAuthorizedException when user is already confirmed - go

Why does cognito throw ErrCodeNotAuthorizedException "NotAuthorizedException" when the status of the user is already confirmed when making a request to cognito to confirm the user.
The documentation specifies that ErrCodeNotAuthorizedException is thrown when a user is not authorized.
https://docs.aws.amazon.com/sdk-for-go/api/service/cognitoidentityprovider/#CognitoIdentityProvider.ConfirmSignUp
How should we handle this case? As it would be unclear if we made a request with invalid client secret as it would throw the same error.

Since the code is the same for the unauthorized case and user already confirmed case, the only possible way to differentiate the cases is to match the awsErr.Message() which provides the clear description of the error.
if awsErr, ok := err.(awserr.Error); ok {
switch awsErr.Code() {
case cognitoidentityprovider.ErrCodeNotAuthorizedException:
if awsErr.Message() == "User cannot be confirm. Current status is CONFIRMED" {
log.Println("Handle user already confirmed")
} else {
log.Println("Handle not authorized case")
}
...
default:
}
}

Related

400 Bad request when generating the Google API access token using Go iamcredentials client API

I am trying to implement iamcredentials Go API client to generate an Access Token to access some Google APIs via REST API, I am using this code
package main
import (
"context"
"log"
"google.golang.org/api/iamcredentials/v1"
)
func main() {
iamcredentialsService, err := iamcredentials.NewService(context.Background())
if err != nil {
log.Println("error initialize iamcredential Service ", err)
return
}
accessTokenCall := iamcredentialsService.Projects.ServiceAccounts.GenerateAccessToken(
"projects/-/serviceAccounts/some-sa#some-project-id.iam.gserviceaccount.com:generateAccessToken",
&iamcredentials.GenerateAccessTokenRequest{
Scope: []string{
iamcredentials.CloudPlatformScope,
},
},
)
iamResp, err := accessTokenCall.Do()
if err != nil {
log.Println("error generate access token", err)
return
}
log.Println(iamResp)
}
But when I tried to run the above snippet, I got this message
go run main.go
error generate access token googleapi: Error 400: Request contains an invalid argument., badRequest
Is there any way to check which one is causing the above response? I am not sure since there isn't any good example of implementation. Any help would be appreciated, Thanks.
Notes :
I have checked following documentation on this topic https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials and this https://pkg.go.dev/google.golang.org/api/iamcredentials/v1#pkg-overview
I have already setup the Service account using Service Account Token Creator role on IAM and also enabled the IAM API from the console
Also I have added GOOGLE_APPLICATION_CREDENTIALS to the environment variables as suggested
#DanielFarrell is right, you need to remove the :generateAccessToken at the end. Here the documentation in the code. Don't hesitate to explore it, it's open source ;)
// GenerateAccessToken: Generates an OAuth 2.0 access token for a
// service account.
//
// - name: The resource name of the service account for which the
// credentials are requested, in the following format:
// `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-`
// wildcard character is required; replacing it with a project ID is
// invalid.
func (r *ProjectsServiceAccountsService) GenerateAccessToken(name string, generateaccesstokenrequest *GenerateAccessTokenRequest) *ProjectsServiceAccountsGenerateAccessTokenCall {
c := &ProjectsServiceAccountsGenerateAccessTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.name = name
c.generateaccesstokenrequest = generateaccesstokenrequest
return c
}

EPIC FHIR SMART Backend Services: { "error": "invalid_client", "error_description": null }

I'm trying to implement the EPIC FHIR SMART Backend Services (Backend OAuth 2.0)
on go programming language.
I've created my dev account, uploaded the public key there, and selecting the backend system as the application audience.
I'm pretty sure my jwt token is correct. I've inspected it on jwt.io, the signature is correct. However, I always get this error:
{ "error": "invalid_client", "error_description": null }
I've tried other possible solutions as well such as:
ensuring the expiration date within the jet claim is below 5 minutes
placing the payload in the body with the correct content type, which is application/x-www-form-urlencoded
ensuring to use the sandbox client_id
using the correct jwt sign in method (RS384)
What should I do to resolve this issue?
Btw, I also saw several discussions on the google groups saying that it's worth to wait for one or two days after the dev account is created.
Below is my code. Appreciate the help!
var (
oauth2TokenUrl = "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token"
sandboxClientID = "..."
privateKey = "..."
)
// load private key
signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
So(err, ShouldBeNil)
// construct jwt claims
now := time.Now()
claims := jwt.MapClaims{
"iss": sandboxClientID,
"sub": sandboxClientID,
"aud": oauth2TokenUrl,
"jti": uuid.New().String(), // fill with reference id
"exp": now.Add(1 * time.Minute).Unix(), // cannot be more than 5 minutes!
}
log.Info(" => claims:", utility.ToJsonString(claims))
// generate signed token using private key with RS384 algorithm
alg := jwt.SigningMethodRS384
signedToken, err := jwt.NewWithClaims(alg, claims).SignedString(signKey)
So(err, ShouldBeNil)
log.Info(" => signed token", signedToken)
// prepare api call payload
payload := map[string]string{
"grant_type": "client_credentials",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": signedToken,
}
// dispatch the api call
req := resty.New().
R().
EnableTrace().
SetFormData(payload)
res, err := req.Post(oauth2TokenUrl)
So(err, ShouldBeNil)
log.Info(" => response status:", res.StatusCode())
log.Info(" => response header:", res.Header())
log.Info(" => response body:", string(res.Body()))
// parse response
resBody := make(map[string]interface{})
err = json.Unmarshal(res.Body(), &resBody)
So(err, ShouldBeNil)
Fantastic, I got it working now.
The solution is simply waiting! it was confusing because I can't find any explanation about this on the doc, and also the error message is not quite friendly.
in summary, after creating dev app and the public key is uploaded there, we have to wait for a few hours/days, and then the credentials will eventually be usable.
The waiting part is applied to both open epic and app orchard dev accounts.
It seems that Epic has some kind of synchronising mechanism which runs once a day. So waiting after account create is the only solution. Please also note that, in app settings after Endpoint URI change you also have to wait some time.
Error { "error": "invalid_client", "error_description": null } also shows up when redirect_uri param is set to something like localhost:3000.
I encountered this problem too. In my case, I was using "Patients" as the "Application Audience" selected for the Epic SMART on FHIR app. I was able to successfully obtain an authorization code on the test server, but when I attempted to exchange it for an access token I received "invalid_client" error message.
The mistake I made is that the redirect_uri in the HTTP POST must be an absolute URL and must match a redirect URI you have specified for your app. If the redirect URI is invalid, the resulting error message will say "invalid client" (which is misleading).
Here is a sample of the Python code I was using...
data = {
'grant_type': 'authorization_code',
'code': request.GET.get('code'),
'redirect_uri': 'http://127.0.0.1:8000/ehr_connection_complete/', # THIS MUST BE AN ABSOLUTE URL
'client_id': '11111111-2222-3333-4444-555555555555',
}
response = post(url, data)
It felt odd to me that an error with the redirect_uri parameter generates an error message about invalid_client, but it's true with Epic's test FHIR server.
I hope this information helps others.

Laravel 8 Socialite check login

is there a way to check if the user has logged in with a Socialite?
because i want to create a post based on this authentication.
what i have done
if (!empty(Socialite::driver('linkedin')->stateless()->user()))
{
$linkedinuser = Socialite::driver('linkedin')->stateless()->user();
dd($linkedinuser);
}
return redirect('/profile/');
i expect to get the dump if user has authenticated with linkedin, or else return profile. Instead, i get an error
GuzzleHttp\Exception\ClientException
Client error: `POST https://www.linkedin.com/oauth/v2/accessToken` resulted in a `400 Bad Request` response: {"error":"invalid_request","error_description":"A required parameter \"code\" is missing"}
how can this be checked ? thanks.

firebase data validation failing

First time working with Firebase on a new project and I'm getting a permission denied message when writing an activity event when I include a validation rule.
The validation rule looks like:
"activity": {
".read": "auth != null",
".write": "auth != null",
".validate": "newData.hasChildren(['user'])",
".indexOn": ["when"]
}
On a new activity event, I push a new entry, grab the token ID and make it (for now) part of the data being pushed. When watching this in debug (using a custom token authentication system) this is what I see. The json pushed has a "user" entry that is the GUID of the auth user so I'm not sure why it's failing. I spaced out the json text.
utility.js (line 1675)
FIREBASE: Attempt to write {
"id":"-K4oomuOpaY4K2aGUYZA",
"imp":false,
"text":"xxx.",
**"user":"0648480c-xxx"**,
"when":1449363973059
} to /activity/## with auth={"uid":"0648480c-xxx","name":"Greg Merideth"}
/activity:.write: "auth != null" => true
/activity:.validate: "newData.hasChildren(['user'])" => false
FIREBASE: Validation failed. firebase.js (line 195)
FIREBASE: Write was denied firebase.js (line 195)
I even tried changing the rule to ".validate": "newData.hasChild('user')" with the same end result.
Is newData looking at the inbound packet or my "auth" packet?
Update (from the comments)
The addition of a new item calls a function passing in the fbActivity handler which then calls:
var message = fbActivity.push({
id: user.fn(),
text: t.val(),
imp: false,
user: user.uid(),
when: new Date().getTime()}
To push the new entry. We're not using the fb.timestamp as our server runs 3 seconds behind fb's so our time stamps come out weird.
I'm guessing that you're calling push() to add a new child under activity. In that case, your rules are missing the extra level that is generated by push():
"activity": {
"$activityid": {
".read": "auth != null",
".write": "auth != null",
".validate": "newData.hasChildren(['user'])",
".indexOn": ["when"]
}
}
If that is the case, please take time to read the Firebase security guide, which explains this and many other useful bits about the language.

Firefox:Problem with Status in OnStateChange in Proxy environment

I am trying to use the status to see if there is an error in C++ XPCOM component in my observer class on Mac.
OnStateChange(
nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRUint32 aStateFlags,
nsresult aStatus)
{
}
In proxy environment the aStatus parameter is always true though the browser fails to load the page.
In non-proxy environments it gives the proper value (error) in status.
You can see it if you try accessing http://10.1.3.3/ (some random IP). With a proxy the status is zero (success) and without a proxy you get an error value.
Should some parameters be set to get the proper error value?
This is the expected behavior if you use an HTTP proxy. A non-zero aStatus means "didn't get any response because of some error". On the other hand, a zero aStatus value means "there was some response, check nsIHttpChannel.responseStatus to see whether the request was successful". That's what you get if the server responds with "404 Not Found" for example - aStatus will be zero (you got a response back) but nsIHttpChannel.responseStatus will be 404.
It's the same with an HTTP proxy because the proxy will always send a response back, probably "502 Bad Gateway" if it couldn't connect to the server. That's what the browser gets so aStatus will be zero and nsIHttpChannel.responseStatus will be 502. So in you code you should do something like this:
OnStateChange(
nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRUint32 aStateFlags,
nsresult aStatus)
{
if (FAILED(aStatus))
{
// Got no response
}
else
{
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest);
PRUint32 status = 0;
if (channel)
channel->GetResponseStatus(&status);
if (status >= 400)
{
// Got an HTTP error
}
else
{
// Success!
}
}
}

Resources