Why does not refresh_token exist in OneDrive API response? - onedrive

After OAuth2.0 authentication, I received user's access_token. In the OneDrive docs below saying what response is expected:
Token response
{
"token_type": "Bearer",
"scope": "user.read%20Fmail.read",
"expires_in": 3600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
"refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4..."
}
But actually I got the response:
{
token_type: 'Bearer',
scope: 'User.Read Files.ReadWrite Files.Read',
expires_in: 3600,
ext_expires_in: 3600,
access_token: 'EwBoA8l6BAAUkj1NuJ...'
}
There was ext_expires_in that did not described in docs. There was not a refresh_token at all! What wrong with it?

Related

Microsoft Graph API - 401 Unauthorized While Creating Chat

I using the graph API v1.0 to create the one-to-One chat,but I found some account get 401 results.I check the Permission from the Api '/me/oauth2PermissionGrants',and I can find the 'Chat.Create' permission.
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#oauth2PermissionGrants",
"value": [
{
"clientId": "9fc4855b-4d7e-443b-a8f0-282690a55a73",
"consentType": "Principal",
"id": "W4XEn35NO0So8CgmkKVacwsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send"
},
{
"clientId": "d39356e1-6d20-4d19-ad54-5278e19b94ec",
"consentType": "Principal",
"id": "4VaT0yBtGU2tVFJ44ZuU7AsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send"
},
{
"clientId": "c81831d1-608e-43fa-abd4-3a09e523cb3c",
"consentType": "Principal",
"id": "0TEYyI5g-kOr1DoJ5SPLPAsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send Files.Read Files.ReadWrite Files.Read.All Files.ReadWrite.All Sites.Read.All Sites.ReadWrite.All"
}
]
}
When I post "https://graph.microsoft.com/v1.0/chats",
set the body like this
{"members":[
{ "user#odata.bind":"https://graph.microsoft.com/v1.0/users('8cddcff8-f959-4e3d-824f-8fe932a7c23c')",
"#odata.type":"#microsoft.graph.aadUserConversationMember",
"roles":["owner"]},
{ "user#odata.bind":"https://graph.microsoft.com/v1.0/users('636f150e-f73c-44d6-be0c-4d543b2b4e5d')",
"#odata.type":"#microsoft.graph.aadUserConversationMember",
"roles":["owner"]
}
],
"chatType":"oneOnOne"
}
It response 401 Authentication failed
{
"error": {
"code": "Unauthorized",
"message": "Authentication failed.",
"innerError": {
"date": "2022-05-17T08:41:05",
"request-id": "de03512e-b97d-4229-b1ce-a73a61ed4f3d",
"client-request-id": "de03512e-b97d-4229-b1ce-a73a61ed4f3d"
}
}
}
When I replace another account's token & teamsUserId and try again ,It returns Ok!
Can you help me check the reason?
First of all check your app id secret and confirm
secondly check that the users you are trying to add have authorized your application.
thirdly check for access token you need scopes and permission according to the token you are sending to the graph
If you are using application token , use default scope and check whether you have added the chat.create application permission else if you are using token on behalf of user you need delegated permission for chat.create application

Question about ASP.NET Core 3 Identity / Identity Server / SPA support for Resource Owner Password Grant Type

As per Authentication and authorization for SPAs, I have created a new SPA with support for API authorization. You can view this on GitHub.
In order to support integration tests, I have added a new client (see appsettings.json) that is allowed the resource owner password grant type:
"SecureSpa.IntegrationTests": {
"Profile": "IdentityServerSPA",
"AllowedGrantTypes": [ "password" ],
"ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ],
"AllowedScopes": [ "SecureSpaAPI", "openid", "profile" ]
}
Then within WeatherForecastControllerTests.cs, I attempt to request the token as follows:
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "SecureSpa.IntegrationTests",
ClientSecret = "secret",
Scope = "SecureSpaAPI openid profile",
UserName = "demouser#securespa",
Password = "Pass#word1"
});
When running the test, I've tried many different combinations, however the results are usually the same (unauthorized_client). This is the relevant log output from Identity Server:
IdentityServer4.Endpoints.TokenEndpoint: Debug: Start token request.
IdentityServer4.Validation.ClientSecretValidator: Debug: Start client validation
IdentityServer4.Validation.BasicAuthenticationSecretParser: Debug: Start parsing Basic Authentication secret
IdentityServer4.Validation.PostBodySecretParser: Debug: Start parsing for secret in post body
IdentityServer4.Validation.SecretParser: Debug: Parser found secret: PostBodySecretParser
IdentityServer4.Validation.SecretParser: Debug: Secret id found: SecureSpa.IntegrationTests
IdentityServer4.Stores.ValidatingClientStore: Debug: client configuration validation for client SecureSpa.IntegrationTests succeeded.
IdentityServer4.Validation.ClientSecretValidator: Debug: Public Client - skipping secret validation success
IdentityServer4.Validation.ClientSecretValidator: Debug: Client validation success
IdentityServer4.Events.DefaultEventService: Information: {
"Name": "Client Authentication Success",
"Category": "Authentication",
"EventType": "Success",
"Id": 1010,
"ClientId": "SecureSpa.IntegrationTests",
"AuthenticationMethod": "SharedSecret",
"ActivityId": "0HLPN4PPDDMCJ",
"TimeStamp": "2019-09-12T02:10:57Z",
"ProcessId": 28948,
"LocalIpAddress": "unknown",
"RemoteIpAddress": "unknown"
}
IdentityServer4.Validation.TokenRequestValidator: Debug: Start token request validation
IdentityServer4.Validation.TokenRequestValidator: Debug: Start resource owner password token request validation
IdentityServer4.Validation.TokenRequestValidator: Error: Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = SecureSpa.IntegrationTests }, details: {
"ClientId": "SecureSpa.IntegrationTests",
"ClientName": "SecureSpa.IntegrationTests",
"GrantType": "password",
"Raw": {
"grant_type": "password",
"username": "demouser#securespa",
"password": "***REDACTED***",
"scope": "SecureSpaAPI",
"client_id": "SecureSpa.IntegrationTests",
"client_secret": "***REDACTED***"
}
}
IdentityServer4.Events.DefaultEventService: Information: {
"Name": "Token Issued Failure",
"Category": "Token",
"EventType": "Failure",
"Id": 2001,
"ClientId": "SecureSpa.IntegrationTests",
"ClientName": "SecureSpa.IntegrationTests",
"Endpoint": "Token",
"GrantType": "password",
"Error": "unauthorized_client",
"ActivityId": "0HLPN4PPDDMCJ",
"TimeStamp": "2019-09-12T02:10:57Z",
"ProcessId": 28948,
"LocalIpAddress": "unknown",
"RemoteIpAddress": "unknown"
}
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 212.96790000000001ms 400 application/json; charset=UTF-8
Is this approach supported? If not, is there an alternative approach that can be used to get the token in order to write integration tests? I'm planning to set up test users along with the test client so that I can test lots of different behaviours.
I continued working on this issue and found that the allowed grant type of password was not being added when the profile is set to IdentityServerSPA. I couldn't see a way to add a client without a profile via appsettings, so I removed the configuration from appsettings and created the clients using this approach:
services.AddIdentityServer()
//.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddIdentityServerSPA("SecureSpa", builder =>
{
builder.WithRedirectUri("https://localhost:44307/authentication/login-callback");
builder.WithLogoutRedirectUri("https://localhost:44307/authentication/logout-callback");
});
options.Clients.Add(new Client
{
ClientId = "SecureSpa.IntegrationTests",
AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedScopes = { "SecureSpaAPI", "openid", "profile" }
});
});
With that in place my tests now run. You can see the final solution here; https://github.com/JasonGT/SecureSpa/.
Everything works fine, however there seems to be a bug (or feature limitation) within DefaultClientRequestParametersProvider. See the 'GetClientParameters' method - if the specified client does not have an associated profile, an InvalidOperationException is thrown.
Let me know if you need more information.
Just for reference' sake: the code above did not work as-is on my end, it broke the SPA sign-in with a redirect_uri invalid exception.
I had to remove the base url, and then it worked:
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");

cochdb permissions roles always "not authorized"

I try to make a user / role authentication (session based) with CouchDB but as soon as I enter a role at a database all users and roles are can access the database -> the are not authorized.
Get the session:
POST http://myhost:1234/_session
It returns (the userCtx object):
{
"ok": true,
"name": "some_user_name",
"roles": [
"developers"
]
}
Then I added the roles to the database:
PUT http://myhost:1234/database/_security
{
"admins": {
"names": [],
"roles": []
},
"members": {
"names": [],
"roles": [
"developers"
]
}
}
and it returns {"ok":true} and I can see the permissions also in fauxton.
When I now try to access the database with
GET http://myhost:1234/database/_all_docs
it returns:
{
"error": "unauthorized",
"reason": "You are not authorized to access this db."
}
If you are using Postman, Add Following key-value in Headers
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Basic " + btoa("YOUR_ADMIN_USER:YOUR_PASSWORD")
ahhh I found the mistake, I was doing the tests with postman and there I did not recognized that the credentials was not send with the requests :-(

Oauth 2.0: I can't get profile info from Google "token info endpoint" by using id_token

I'm trying to get user info (profile,email) from Google by using OAuth 2.0.
But "token info endpoint" did not return profile info even though I set "profile" to scopes.
I followed the doc of Google sign-in for iOS. (https://developers.google.com/identity/sign-in/ios/backend-auth)
I couldn't figure out why this end point doesn't return profile info as I expected.
First I get Token by oauth2.0 (as a test, I got token using Rails)
def gmail
require 'oauth2'
client = OAuth2::Client.new(
'Client-id',
'client-secret',
{
site: 'https://accounts.google.com/',
authorize_url: 'o/oauth2/auth',
}
)
redirect_to client.auth_code.authorize_url(
redirect_uri: 'http://localhost:3000/google_signup',
scope: 'email profile',
)
end
token = client.auth_code.get_token(
params[:code],
redirect_uri: 'http://localhost:3000/gmail_signup',
and I get id_tokenfrom this token.
then, send GET request to "token info endpoint".
"https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=id_token"
but response didn't contain profile info.
{
"azp": "azp",
"aud": "aud",
"sub": "sub",
"email": "email#gmail.com",
"email_verified": "true",
"at_hash": "at_hash",
"exp": "TIMESTAMP",
"iss": "accounts.google.com",
"iat": "iat",
"alg": "alg",
"kid": "kid"
}
The response was supposed to be like this.
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

Using the access token with the SkyDrive API

I have been trying to get access to the json result with the following link:
https://apis.live.net/v5.0/file.a4423f3123801749.A4423F3123801749!418
But as you can see by clicking on it yourself, you need an access token.
I already have an access token, but it only lasts for 3600 seconds (1 hour).
Is there a way to get the results of the link (the json shown below) without the access token expiring? I know there is a refresh token, but I am unsure how to use it.
{
"id": "file.a4423f3123801749.A4423F3123801749!418",
"from": {
"name": "Andrew Wong",
"id": "a4423f3123801749"
},
"name": "Mod Permissions.xlsx",
"description": "",
"parent_id": "folder.a4423f3123801749.A4423F3123801749!129",
"size": 89956,
"upload_location": "https://apis.live.net/v5.0/file.a4423f3123801749.A4423F3123801749!418/content/",
"comments_count": 0,
"comments_enabled": true,
"is_embeddable": true,
"source": "https://hvbqwg.dm2302.livefilestore.com/y2m6t-kEOaAd1qXi2n4cvNuVCMqU2Is3Ft_7g7UGM1h6Ib8oyGSFzT70rT3F3mz5PFsrzUDkyAfhYoh1YIZWNY3INmCIKheJpZWoUVTvz-xh5I/Mod%20Permissions.xlsx?psid=1",
"link": "https://skydrive.live.com/redir.aspx?cid=a4423f3123801749&page=view&resid=A4423F3123801749!418&parid=A4423F3123801749!129",
"type": "file",
"shared_with": {
"access": "Public"
},
"created_time": "2014-01-16T07:06:41+0000",
"updated_time": "2014-01-16T07:14:51+0000",
"client_updated_time": "2014-01-16T07:14:51+0000"
}
Do a post to https://login.live.com/oauth20_token.srf to convert your refresh_token to an access_token. Read more in MS documentation bullet #6.
Here are a sample node.js code
var options,request;
request = require('request');
options = {
url: 'https://login.live.com/oauth20_token.srf',
form: {
client_id: YOUR CLIENT_ID,
redirect_uri: YOUR REDIRECT_URI,
client_secret: YOUR CLIENT_SECRET,
refresh_token: YOUR REFRESH_TOKEN,
grant_type: 'refresh_token'
},
headers: {
'Accept': 'application/json'
}
};
request.post(options, function(err, response, data) {
});