Skip to content

Commit 3d4698f

Browse files
committed
init
0 parents  commit 3d4698f

File tree

10 files changed

+352
-0
lines changed

10 files changed

+352
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/bin
2+
/.idea

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# ms-graph-auth-helper
2+
3+
一个可以快速帮助获取Microsoft Graph API(OneDriver)令牌的小工具
4+
5+
~~在弄网盘API的时候觉得太麻烦了就搞了个这个~~
6+
7+
![ms-auth-run](https://user-images.githubusercontent.com/7535224/147150440-a5074cc7-ce73-4663-b9ee-09a323949666.png)
8+
9+
## 如何使用
10+
11+
在获取令牌时,请按照以下步骤操作
12+
13+
#### 注册新应用
14+
15+
- 打开[Azure应用管理面板](https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)注册新的应用
16+
17+
- **受支持的帐户类型** 选项选择 **任何组织目录(任何 Azure AD 目录 - 多租户)中的帐户和个人 Microsoft 帐户(例如,Skype、Xbox)**
18+
19+
- 重定向URL(可选)中选择 **Web** 类型并将URL值设置为 **`http://localhost:11451/auth`**
20+
21+
#### 权限
22+
23+
- 切换至 **API权限** 选项卡点击 **添加权限**
24+
25+
- 选择 **Microsoft Graph** 分类
26+
27+
- 使用搜索功能找到并勾选以下权限:
28+
29+
- Files.Read
30+
31+
- Files.Read.All
32+
33+
- Files.ReadWrite
34+
35+
- Files.ReadWrite.All
36+
37+
- offline_access
38+
39+
- 点击 **添加权限** 完成授权
40+
41+
#### 应用程序(客户端) ID [Client Id]
42+
43+
- 切换至 **概述** 选项卡复制**应用程序(客户端) ID****自行保管**
44+
45+
#### 机密值[Client Secret]
46+
47+
- 切换至 **证书和密码** 选项卡
48+
49+
- 点击 **新建客户端密码** 并创建一个新的密钥
50+
51+
- 创建完成后复制密钥的值并**自行保管**
52+
53+
#### 启动工具按照提示完成令牌的获取

browser.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package main
2+
3+
import (
4+
"os/exec"
5+
)
6+
7+
func OpenBrowser(path string) error {
8+
err := exec.Command("rundll32", "url.dll,FileProtocolHandler", path).Start()
9+
if err != nil {
10+
return err
11+
}
12+
return nil
13+
}

go.mod

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module ms-graph-auth-helper
2+
3+
go 1.17
4+
5+
require github.com/gin-gonic/gin v1.7.7
6+
7+
require (
8+
github.com/gin-contrib/sse v0.1.0 // indirect
9+
github.com/go-playground/locales v0.13.0 // indirect
10+
github.com/go-playground/universal-translator v0.17.0 // indirect
11+
github.com/go-playground/validator/v10 v10.4.1 // indirect
12+
github.com/golang/protobuf v1.3.3 // indirect
13+
github.com/json-iterator/go v1.1.9 // indirect
14+
github.com/leodido/go-urn v1.2.0 // indirect
15+
github.com/mattn/go-isatty v0.0.12 // indirect
16+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
17+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
18+
github.com/ugorji/go/codec v1.1.7 // indirect
19+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
20+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
21+
gopkg.in/yaml.v2 v2.2.8 // indirect
22+
)

go.sum

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
5+
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
6+
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
7+
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
8+
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
9+
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
10+
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
11+
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
12+
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
13+
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
14+
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
15+
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
16+
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
17+
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
18+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
19+
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
20+
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
21+
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
22+
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
23+
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
24+
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
25+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
26+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
27+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
28+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
29+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
30+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
31+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
32+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
33+
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
34+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
35+
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
36+
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
37+
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
38+
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
39+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
40+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
41+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
42+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
43+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
44+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
45+
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
46+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
47+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
48+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
49+
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
50+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
51+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
52+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
53+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
54+
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
55+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

main.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
"time"
9+
)
10+
11+
var console = bufio.NewReader(os.Stdin)
12+
13+
func main() {
14+
initLog()
15+
//重定向服务器
16+
go StartServer()
17+
fmt.Println("将跳转浏览器授权")
18+
fmt.Println("请输入App的应用程序(客户端) ID [Client Id]")
19+
clientId := readLine()
20+
err := OpenBrowser(BuildMsAuthorizeUrl(clientId))
21+
if err != nil {
22+
fmt.Printf("启动浏览器时发生错误\r\n%s", err.Error())
23+
}
24+
fmt.Println()
25+
clientCode := <-CodeCh
26+
if clientCode != nil {
27+
fmt.Printf("获取到code(%v)\r\n", len(*clientCode))
28+
} else {
29+
fmt.Println("获取code失败,请检查client_id和网络设置")
30+
_ = readLine()
31+
return
32+
}
33+
fmt.Println()
34+
fmt.Println("请输入App的机密值[Client Secret]")
35+
clientSecret := readLine()
36+
fmt.Println()
37+
tokenData, err := MsTokenRequest(clientId, clientSecret, *clientCode)
38+
if err != nil {
39+
fmt.Printf("获取token时发生错误\r\n%s", err.Error())
40+
}
41+
fmt.Printf("获取到token(%v)\r\n", len(tokenData.AccessToken))
42+
fmt.Printf("获取到refresh-token(%v)\r\n", len(tokenData.RefreshToken))
43+
saveData := TokenResult{
44+
ClientId: clientId,
45+
ClientCode: *clientCode,
46+
Secret: clientSecret,
47+
AccessToken: tokenData.AccessToken,
48+
RefreshToken: tokenData.RefreshToken,
49+
}
50+
jsonBytes, err := saveData.Save()
51+
if err != nil {
52+
fmt.Println("保存token信息失败,请自行复制获取到的token")
53+
time.Sleep(time.Second * 3)
54+
fmt.Println(string(*jsonBytes))
55+
}else{
56+
fmt.Println("token信息已保存至工具根目录的result.json文件中")
57+
}
58+
fmt.Println("按下回车退出本工具")
59+
readLine()
60+
}
61+
62+
func readLine() (str string) {
63+
str, _ = console.ReadString('\n')
64+
str = strings.TrimSpace(str)
65+
return
66+
}
67+
68+
func initLog() {
69+
fmt.Println("Ciallo~(∠・ω< )⌒☆")
70+
fmt.Println("本工具将帮助你获取微软Graph的API的访问令牌,获取到的结果将保存到工具运行的目录下")
71+
fmt.Println()
72+
fmt.Println("请先保证使用本工具前已经在Microsoft Azure重创建了新的应用,并满足以下条件:")
73+
fmt.Println("1.并授予了offline_access Files.Read Files.Read.All Files.ReadWrite Files.ReadWrite.All权限")
74+
fmt.Println("2.重定向URL选择了(Web)类型,并设置值为(http://localhost:11451/auth)")
75+
fmt.Println("3.在证书和密码选项卡中创建并保存了机密值(Client Secret)")
76+
fmt.Println("请在确认以上条件后按回车继续")
77+
_ = readLine()
78+
}

ms_token_resp_model.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package main
2+
3+
type TokenResp struct {
4+
TokenType string `json:"token_type"`
5+
Scope string `json:"scope"`
6+
ExpiresIn int `json:"expires_in"`
7+
ExtExpiresIn int `json:"ext_expires_in"`
8+
AccessToken string `json:"access_token"`
9+
RefreshToken string `json:"refresh_token"`
10+
}

redirect_server.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
)
6+
7+
// CodeCh 用于传输服务器返回的client-code
8+
var CodeCh = make(chan *string)
9+
10+
func StartServer() {
11+
gin.SetMode(gin.ReleaseMode)
12+
router := gin.New()
13+
router.GET("/auth", authMs)
14+
err := router.Run(":11451")
15+
if err != nil {
16+
return
17+
}
18+
}
19+
20+
func authMs(c *gin.Context) {
21+
code := c.Query("code")
22+
if len(code) != 0 {
23+
CodeCh <- &code
24+
c.String(200, "获取client-code成功,请回到工具执行下一步操作\r\n\r\n%s" , code)
25+
}else{
26+
CodeCh <- nil
27+
c.String(200, "获取client-code失败,请检查网络设置并再次运行")
28+
}
29+
}

token_result.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
)
7+
8+
type TokenResult struct {
9+
ClientId string `json:"client-id"`
10+
ClientCode string `json:"client-code"`
11+
Secret string `json:"secret"`
12+
AccessToken string `json:"access-token"`
13+
RefreshToken string `json:"refresh-token"`
14+
}
15+
16+
func (res *TokenResult) Save() (*[]byte, error) {
17+
file, err := os.Create("result.json")
18+
if err != nil {
19+
return nil, err
20+
}
21+
defer func(file *os.File) {
22+
_ = file.Close()
23+
}(file)
24+
if err != nil {
25+
return nil, err
26+
}
27+
jsonBytes, err := json.MarshalIndent(res, ""," ")
28+
if err != nil {
29+
return nil, err
30+
}
31+
_, err = file.Write(jsonBytes)
32+
return &jsonBytes, err
33+
}

util.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"net/http"
10+
"net/url"
11+
"strings"
12+
)
13+
14+
func BuildMsAuthorizeUrl(clientId string) string {
15+
u, _ := url.Parse("https://login.microsoftonline.com/common/oauth2/v2.0/authorize")
16+
urlQuery := u.Query()
17+
urlQuery.Set("client_id", clientId)
18+
urlQuery.Set("redirect_uri", "http://localhost:11451/auth")
19+
urlQuery.Set("response_type", "code")
20+
u.RawQuery = urlQuery.Encode()
21+
return fmt.Sprintf("%s&scope=offline_access+Files.Read+Files.Read.All+Files.ReadWrite+Files.ReadWrite.All", u.String())
22+
}
23+
24+
func MsTokenRequest(clientId, clientSecret, clientCode string) (*TokenResp, error) {
25+
data := url.Values{}
26+
data.Set("client_id", clientId)
27+
data.Set("redirect_uri", "http://localhost:11451/auth")
28+
data.Set("client_secret", clientSecret)
29+
data.Set("code", clientCode)
30+
data.Set("grant_type", "authorization_code")
31+
r, err := http.NewRequest(http.MethodPost,
32+
"https://login.microsoftonline.com/common/oauth2/v2.0/token",
33+
strings.NewReader(data.Encode()))
34+
if err != nil {
35+
return nil, err
36+
}
37+
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
38+
client := &http.Client{}
39+
resp, err := client.Do(r)
40+
if resp.StatusCode != http.StatusOK {
41+
errInfo := fmt.Sprintf("response http code %v", resp.StatusCode)
42+
return nil, errors.New(errInfo)
43+
}
44+
defer func(Body io.ReadCloser) {
45+
_ = Body.Close()
46+
}(resp.Body)
47+
body, err := ioutil.ReadAll(resp.Body)
48+
if err != nil {
49+
return nil, err
50+
}
51+
tokenData := TokenResp{}
52+
err = json.Unmarshal(body, &tokenData)
53+
if err != nil {
54+
return nil, err
55+
}
56+
return &tokenData, nil
57+
}

0 commit comments

Comments
 (0)